본문의 이미지 주소를 일괄로 교정해 달라는 요청을 받았다. 파일명이 한글로 들어 있는 것을 인코딩된 형태로 바꿔야 한다는 내용이었다.
Table of contents
Open Table of contents
대상을 좁힌 주소 유형
본문의 이미지 주소가 두 유형이었다. 하나는 /media/{id} 식별자로만 만들어지는 고정 경로라 파일명과 무관하고 다른 하나는 file_name이 그대로 들어간다.
앞쪽은 애초에 교정 대상이 아니므로 대상이 절반쯤 줄었다. 무엇이 영향을 받는지를 먼저 가르지 않으면 안 바꿔도 될 것까지 건드린다.
검증 — 요청 하나로 확인한 전제
교정하기 전에 지금 정말 안 되는지를 확인했다. 한글 파일명을 가진 미디어 몇 개를 골라 curl -I로 실제로 요청했더니 200이 왔다.
잘 되고 있었다. 왜 되는지 보니 저장 규칙이 collection_name마다 달라서 thumb과 gallery는 rawurlencode된 형태로 저장되고 body는 한글 그대로 저장되고 있었다.
원인 — 3자 정합이라는 정답
body 컬렉션은 S3 키와 file_name과 본문의 src가 전부 한글이었다. 셋이 정합이라 요청이 성공한다.
즉 이 컬렉션에서는 한글이 잘못된 상태가 아니라 정답이었고 요청에 딸려 온 전제가 틀렸다. 요청대로 일괄 교정했으면 본문 주소만 인코딩 형태로 바뀌고 저장소 키는 한글 그대로여서 정상 동작 중인 수백만 건이 매칭에 실패했을 것이다.
판단 기준 — 모집단이 다른 기존 명령
두 가지 방법이 있었는데 기존 media:backfill-filenames 명령에 끼워 넣는 것과 별도 명령으로 분리하는 것이다. id 범위를 확인하니 백필 대상 경계보다 이번 건들이 전부 아래에 있었다.
뒤쪽을 골랐다. 이유는 모집단이 다르므로 기존 명령에 끼워 넣으면 그 명령의 WHERE id > 조건이 바뀌고 다른 것들까지 대상이 돼서다. 대신 비슷한 명령이 둘 남는 것을 감수했다.
교훈 — 설계 순서와 소비 경로
이 조사에서 순서가 정해졌다. 인코딩 교정을 설계할 때는 대상 컬렉션을 먼저 특정하고 소비 경로를 실패 사례 한 건으로 실측해 타깃을 확정한다.
어떻게 저장돼 있는지만 보면 안 되고 누가 그것을 가져가는지를 봐야 하는데 외부가 재호스팅하는 경로와 브라우저가 <img src>로 직접 부르는 경로는 인코딩 처리가 다를 수 있다. 이론상 깨진다가 아니라 실제로 깨진 건 하나를 재현해야 타깃이 확정된다.
이 건의 요지는 요청에 딸려 온 전제를 확인한다는 것 하나다. 한글 파일명이 문제라는 것은 요청자의 판단이고 확인하는 데는 요청 한 번이면 됐다.
정리
- 같은 종류의 데이터도 컬렉션마다 저장 규칙이 다를 수 있다
- 저장소와 데이터베이스와 참조가 정합이면 비ASCII 파일명도 정상이다
- 교정 전에 실제로 안 되는지
curl -I하나로 확인한다 - 일괄 교정이 정상 동작 중인 것을 깨뜨릴 수 있다
- 참조 형태가 여럿이면 영향받는 유형만 대상으로 좁힌다
id범위가 다르면 모집단이 다르므로 기존 명령에 끼워 넣지 않는다- 설계는 대상 특정과 소비 경로 실측 순으로 한다
- 요청에 딸려 온 전제를 확인한다