Skip to content
isdnetworks
Go back

전수 스캔 대신 헤더

(수정됨)

깨진 상품 이미지를 찾아야 해서 복구 도구를 만들었는데 시험할 대상이 필요했다. 도구의 --check 모드를 돌려 보니 예상 소요 시간이 몇 시간으로 나왔다.

Table of contents

Open Table of contents

문제 — 세 시간짜리 전수 점검

그 점검은 S3 버킷을 ListObjects 로 전수로 훑으면서 사만 건이 넘는 대상을 하나씩 HeadObject 로 확인한다. 지금 내가 필요한 것은 깨진 사례 몇 개이지 전체 목록이 아니었다.

목적에 비해 수단이 훨씬 크면 기다리는 시간이 그대로 낭비가 된다. 그래서 실행을 중단하고 더 값싼 판별 수단이 있는지부터 찾아봤다.

원인 — 식별자에서 계산되는 주소

마켓의 썸네일 주소 규칙을 보니 product_id 의 뒷자리를 쪼개 /thumb/<ab>/<cd>/<id>.jpg 디렉터리를 만드는 방식이었다. 즉 데이터베이스 조회 없이 식별자만으로 주소를 계산할 수 있었다.

그러면 저장소를 거치지 않고 그 주소를 CDN 에 직접 물어볼 수 있다. 확인해야 할 대상이 S3 가 아니라 공개된 URL 로 바뀐 셈이다.

해결 — 헤더에 남은 지문

정상 이미지가 없으면 대체 이미지가 응답으로 오는데 그 응답의 Content-Type 과 Content-Length 가 항상 같았다. .jpg 주소에 image/png 가 오는 어긋남도 그 지문 가운데 하나였다.

본문을 받지 않고 헤더만 봐도 판별되므로 요청 하나의 비용이 크게 내려간다. 두 가지 방법이 있었는데 --check 모드를 그대로 기다리는 것과 curl -I 를 xargs -P 로 병렬로 돌리는 것이다. 뒤쪽을 골랐다. 이유는 RFC 9110 이 HEAD 를 본문 없이 GET 과 같은 헤더를 돌려주는 메서드로 정의하므로 판별에 필요한 것만 받아서다. 대신 CDN 캐시에 든 옛 응답을 볼 수 있다는 것을 감수하고 표본 일부는 GET 으로 재확인했다. 식별자 수백 개를 병렬로 물으니 몇 시간짜리 확인이 수십 초로 끝났다.

주의 — 첫 표본에서 나온 0건

처음에는 최근 등록된 상품에서 표본을 뽑았고 깨진 것이 하나도 안 나왔다. 그 결과만 보고 깨진 것이 없다고 결론 낼 뻔한 자리였다.

product_id 가 AUTO_INCREMENT 순번이라 구간을 나눠 다시 뽑아 보니 오래된 구간에만 몇 퍼센트가 몰려 있었다. 시간이 지나며 쌓인 문제이므로 오래된 쪽에 군집하는 것이 당연한 분포였다.

판단 기준 — 구간을 나눠 뽑는 이유

최근 구간에서만 뽑았으면 깨진 상품이 없다고 보고했을 것이고 그 보고를 받으면 복구 도구를 안 만든다. 실제로는 상당한 비율이 깨져 있는데도 그렇게 된다.

무작위 표본도 등록량이 늘고 있으면 최근 쪽으로 치우치므로 안전하지 않다. 구간을 명시적으로 나눠 각각 뽑는 것이 이런 분포에서 유일하게 안전한 방법이었다.

정리


Share this post on:

Previous Post
생성이라는 로그와 실제 갱신
Next Post
소진된 작업과 재현 불가