같은 이미지인데 미리보기가 이상하게 나온다고요?

같은 이미지인데 미리보기가 이상하게 나온다고요?

모두가 알지만 가끔 깜빡하는 MIME 타입 이야기

최근에 어떤 서비스를 통해 Facebook에서 보여주는 링크의 미리보기 이미지를 바꾼 적이 있다. 그런데 링크 미리보기에서 계속 내가 의도하지 않았던 모양으로 나왔다. 이미지가 꽉 채워지고 아래에 설명이 나오는 형태를 생각했는데, 이미지가 정사각형으로 짤려나왔다 😇

갑자기 열받게 하는 미리보기 이미지 ☝️ 갑자기 열받게 하는 미리보기 이미지

보통은 이미지 크기 때문에 이런 문제가 발생할 수 있다. 미리보기 이미지는 1200px * 630px, 그게 아니더라도 1.9:1의 비율을 맞춰줘야, 링크 미리보기에서 이미지가 꽉 채워져서 나온다. 그런데 이미지 사이즈는 정확히 1200px * 630px였다. 무엇이 문제일까?

  • og:image:widthog:image:height 를 주지 않아서? → 이는 링크 미리보기의 초기 정보를 구성할 때의 속도를 높여주는 부가 정보이지, 딱히 넣어주지 않아도 시간이 지나면 알아서 잘 된다.
  • og:typearticle 이 아니어서? → og:typewebsite 로 된 다른 사이트들에서 문제가 없었다.
  • 이미지의 파일 타입이 png 여서? → 예전에 Facebook에 그런 버그가 아주 잠깐 있었는데 지금은 문제가 없다.
  • Facebook에서 머신러닝으로 이미지 정가운데에 콘텐츠가 안오면 저렇게 만들기로 정책을 바꿨다? → 비슷한 계열의 정책이 광고에 있긴 한데… 설마 🤯
  • Facebook에서 미리보기 이미지를 긁어가다 뻑이 났다?

문제의 실마리는 가장 마지막 가설을 확인해보다가 잡게 되었다. 가설의 검증을 위해 일괄 무효화 도구를 돌린 뒤 공유 디버거를 통해 다시 링크를 스크랩했다.

그랬더니 ‘해결해야 하는 경고’ 영역에 ‘링크 URL이 올바르지 않다’는 오류가 떴다. 이미지 자체는 깨지지 않았기에 S3에 이미지를 올려 URL을 만들었다. 그리고 그 URL을 og:image 에 적용하였다. 그 후에 다시 링크를 스크랩했더니 잘 뜬다 …?

image.png

같은 이미지를 업로드했는데 다르게 뜰 수 있던가?

URL을 통해 이미지를 불러오니까, Header를 들여다보면 뭔가 차이가 있을 것이라고 생각했다. Postman을 사용해 요청을 날린 후에 Headers를 들여다보기로 했다.

(참고로, curl 써도 되긴 하는데 ‘GUI를 쓸 수 있을 때까지는 GUI를 쓰자는 주의’기 때문에 Postman을 사용했다) 각각 미리보기가 이상하게 뜨는 URL(위) / 정상적인 이미지를 제공하는 URL(아래)의 Headers다. 차이점이 보이는가?

미리보기 이미지가 이상하게 뜨는 URL ☝️ 미리보기 이미지가 이상하게 뜨는 URL

정상적인 미리보기 이미지를 제공하는 URL ☝️ 정상적인 미리보기 이미지를 제공하는 URL

몇몇 차이가 있겠지만, 가장 중요한 것은 Content-Type이다. 문제가 되는 URL에서는 binary/octet-stream 으로 뜨고, 정상적인 URL에서는 image/jpeg 로 뜬다.

Content-Type. 즉 MIME 타입¹이 잘못 설정되어 Facebook에서 해당 URL을 통해 이미지를 가져올 때 오류가 난 것으로 추측하였다.


MIME 타입이란?

MIME 타입 = 파일 해독을 위한 설명 정도로 생각을 하고 있다.

메일을 생각해보면, 글 뿐만 아니라 사진과 영상, 음악 등 다양한 파일을 업로드하고 다운로드할 수 있다. 각각의 파일은 0과 1로 구성되어 있다. 근데 메일은 텍스트를 보내는 방식이다. 그려면 보내는 쪽이 파일 → 텍스트로 바꿔주고, 받는 쪽에서 텍스트 → 파일로 바꿔주면 된다.

근데 만약에 ‘파일 → 텍스트로 바꾸는 방식’과 ‘텍스트 → 파일로 바꾸는 방식’이 다르면 어떻게 될까? 서로 파일을 못 열어보는 참사가 발생한다 🤬

여기서 MIME 타입이 등장한다. 서로 변환하는 과정에서 공통된 방식을 쓰되, 이 텍스트를 풀면 이미지가 나오는지, 사진이 나오는지, 아니면 그냥 다른 파일이 나오는지… 등의 설명을 달아주면 깨지지도 않고 텍스트만 받아도 파일로 바꿔볼 수 있다. ‘아하’ 정도만 해도 괜찮을 것 같다는 생각이 들어 가볍게 개념을 정리한다.


보통 이미지들은 MIME 타입에 image/png, image/jpeg 등으로 표현이 된다. 만약에 HTML을 조금 더 안다면 Input 태그의 type이 file일 때, accept="image/*" 처럼 파일 업로드 시 타입을 제한할 수 있다는 것과도 연관지을 수 있을 것이다.

그리고 문제가 되었던 MIME 타입인 binary/octet-stream은 모르는 파일 타입들을 나타낼 때 쓴다. 텍스트도 아니고, 이미지도 아니고, 뭣도 아닌 친구들을 지칭할 때 이 녀석을 사용한다.

참고로, Chrome 같은 브라우저에서 MIME 타입이 binary/octet-stream인 링크의 URL을 입력해서 들어가면 해당 파일이 다운로드 된다. MIME 타입이 image/* 면? 그 파일이 그대로 보여지게 된다.

image.png

MIME 타입과 관련해서 보다 자세한 내용은 아래에서 참고할 수 있다.


어쨌든 이 문제를 해당 서비스에 알렸다. 아마 수 일 내로 해결되지 않을까. 갑자기 오랜만에 뜬금 없는 삽질을 했는데, 그래도 이렇게 흐릿했던 지식을 짚고 넘어갈 때 재미를 느끼곤 한다.

¹ Multipurpose Internet Mail Extension, 다목적으로 인터넷 메일을 확장.