카카오톡 공유 카드에 그림이 빠질 때 — 스크레이퍼는 오래 기다려 주지 않는다
어제는 되던 카톡 공유 카드가 오늘은 그림 없이 올라갔다. 코드는 그대로였다. 원인은 그림을 그리는 4초였다.

우리 서비스에는 그날 한 기록을 카카오톡으로 공유하는 기능이 있다. 공유하면 단톡방에 그림이 들어간 카드가 올라간다. 한 사용자는 이 카드를 매일 가족 단톡방에 올린다.
어느 날 그 카드가 그림 없이 올라갔다. 전날까지는 멀쩡했다. 코드도 바뀌지 않았다. 서버 기록을 보니 원인은 시간이었다. 카카오가 그림을 가져가려고 기다리다가 먼저 끊었다.
결론부터 적는다.
| 항목 | 고치기 전 | 고친 뒤 |
|---|---|---|
| 그림을 만드는 때 | 카카오가 가져갈 때마다 | 공유 링크를 만드는 순간 한 번 |
| 그림 응답 시간 | 2~4.35초 | 0.05~0.22초 |
| 카카오가 가져가다 끊은 횟수 | 세 번 중 두 번 | 끊길 만큼 걸리지 않음 |
1. 공유 카드의 그림은 어디서 오나
카카오톡은 링크를 받으면 그 페이지를 직접 열어 본다. 페이지의 og:image 주소를 찾아 그림을 가져오고, 그 그림으로 카드를 만든다. 이 일을 하는 카카오 쪽 프로그램을 스크레이퍼라고 부른다.
우리 카드 그림은 미리 만들어 둔 파일이 아니었다. Next.js 의 opengraph-image 기능으로, 요청이 올 때마다 서버가 그 자리에서 그렸다. 기록마다 날짜와 숫자가 달라서 그렇게 만들었다.
2. 서버 기록에 남은 것
nginx 접속 기록에서 카카오 스크레이퍼의 요청만 골라 봤다. 같은 카드 그림 주소에 요청이 세 번 와 있었다.
| 순서 | 응답 코드 | 뜻 |
|---|---|---|
| 1 | 499 | 서버가 답하기 전에 카카오가 먼저 끊음 |
| 2 | 499 | 같음 |
| 3 | 200 | 정상으로 받아 감 |
499 는 nginx 가 남기는 코드다. 요청한 쪽이 응답을 기다리다 연결을 끊었다는 뜻이다. 서버가 틀린 게 아니라 느렸던 것이다. 전날 카드는 한 번에 200이었다.
3. 얼마나 느렸나
그림을 그리는 시간을 재 봤다.
- 서버가 막 다른 요청을 처리한 따뜻한 상태: 약 2초
- 한동안 요청이 없던 서버 프로세스가 처음 그릴 때: 4.35초
그림 하나에 글꼴을 읽고, 레이아웃을 계산하고, PNG 로 굽는 과정이 모두 들어 있다. 사람이 페이지를 열 때는 2초도 참을 만하다. 하지만 스크레이퍼는 오래 기다려 주지 않는다. 몇 초를 기다리는지는 공개된 숫자가 없다. 우리 기록으로는 4초대 요청이 끊겼다.
코드가 같은데 전날은 되고 이날은 안 된 이유가 이것이다. 그리는 시간이 그때그때 서버 상태에 따라 2초가 되기도, 4초가 넘기도 했다.
4. 고친 방법 — 공유하는 순간 미리 그린다
카카오가 올 때 그리지 말고, 공유 링크를 만드는 순간 서버가 먼저 한 번 그려 두기로 했다. 사용자가 공유 버튼을 누르면 이런 순서로 돈다.
| 순서 | 하는 일 |
|---|---|
| 1 | 공유 링크(토큰)를 만든다 |
| 2 | 같은 서버에서 그 카드 그림을 한 번 그려 디스크에 저장한다(최대 9초) |
| 3 | 카카오톡 공유 창을 연다 |
| 4 | 카카오가 그림을 가지러 오면 저장본을 바로 준다 |
2번이 실패해도 공유는 그대로 진행한다. 그러면 예전처럼 그 자리에서 그린다. 캐시는 덤이고, 없어도 서비스가 멈추지 않게 했다.
구현하며 신경 쓴 점이 세 가지 있다.
- 메모리가 아니라 디스크에 저장했다. 서버 프로세스가 여러 개(pm2 클러스터)라서, 한 프로세스 메모리에 저장하면 카카오 요청이 다른 프로세스로 갔을 때 없다. 모두가 같이 보는 디스크 폴더에 둔다.
- 다 쓴 뒤에 이름을 바꿨다. 임시 파일에 먼저 쓰고, 다 쓰면 진짜 이름으로 바꾼다. 반쯤 쓴 그림을 누가 읽어 가지 않게 하려는 것이다.
- 30일 지난 파일은 지운다. 카드 그림은 공유한 순간의 기록이라 내용이 바뀌지 않는다. 오래 둬도 되지만 무한히 쌓이지 않게 했다.
5. 이미 그림 없이 나간 카드는
고친 뒤에도 이미 보낸 카드는 그대로였다. 카카오는 한 번 가져간 결과를 주소별로 한동안 기억한다. 실패도 기억한다. 그래서 수정은 다음 공유부터 적용됐다.
이미 나간 카드를 고치고 싶다면 카카오 개발자 사이트의 공유 디버거에서 그 주소의 캐시를 지우고 다시 가져가게 할 수 있다. 가장 확실한 건 처음부터 그림이 빨리 나가게 하는 것이다.
정리 — 공유 카드에 그림이 빠질 때 볼 순서
| 순서 | 볼 것 | 이렇게 나오면 |
|---|---|---|
| 1 | 페이지에 og:image 가 있나 | 없으면 메타 태그 문제 |
| 2 | 그 그림 주소가 브라우저에서 열리나 | 안 열리면 경로·권한 문제 |
| 3 | 서버 기록에서 카카오 요청의 응답 코드 | 499면 느려서 끊긴 것 |
| 4 | 그림 응답 시간 | 몇 초씩 걸리면 미리 그려 두기 |
| 5 | 이미 나간 카드 | 공유 디버거로 캐시 초기화 |
그림을 요청마다 그리는 방식은 편하지만, 기다려 주지 않는 손님이 올 때는 약점이 된다. 이 경우 손님은 카카오였다. 그 손님이 오기 전에 미리 그려 두면 된다.
태그