이미지 404 인데 에러 로그에 안 남는다 — 조용한 어긋남
DB에는 사진 주소가 있고 저장소엔 파일이 없었다. 한 달 반 동안 아무도 몰랐다.
아트페어 앱 첫 화면 썸네일을 손보다가, 어느 페어 카드가 이상하게 비어 보였다. 개발자 도구를 열어보니 작품 사진 자리에 <img> 태그는 있는데 그림이 안 나온다. 주소를 그대로 복사해서 쳐봤다.
{"statusCode":"404","error":"not_found","message":"Object not found"}
데이터베이스에는 사진 주소가 저장돼 있는데, 그 주소가 가리키는 파일이 저장소에 없었다.
한 건이겠거니 하고 전수로 세봤다. 작품 77개 중 사진이 있는 게 77개, 그중 외부 이미지 30개를 빼면 47개. 그 47개 중 2개가 파일이 없었다. 등록일은 6월 26일, 발견한 날은 8월 11일이었다.
한 달 반 넘게 그 상태였다.
이유는 단순했다. 예전에 테스트용 데이터를 정리하면서 저장소 파일만 지웠고, 데이터베이스 행은 남겨뒀다.
「놓친 에러」가 아니었다
처음엔 이걸 놓친 에러로 분류했다. 에러 수집 도구를 안 붙여서 못 본 거라고 생각했다.
그런데 아니었다.
이건 애초에 에러가 아니었다. 서버는 200을 정상적으로 응답했다. 페이지도 멀쩡히 그려졌다. 브라우저 콘솔에도 빨간 줄이 없다. 이미지 하나가 404를 받은 건 사실이지만, 브라우저 입장에선 그럴 수도 있는 일이다. 광고 차단기가 막았을 수도 있고 네트워크가 끊겼을 수도 있으니까.
그러니까 아무것도 안 터졌다. 터질 게 없으니 로그에도 안 남고, 알림도 안 오고, 아무도 모른다. 사용자가 화면을 봐야만 알 수 있는데, 그 페어를 열어본 사람이 그 사이에 없었을 뿐이다.
여기서 두 가지가 완전히 다른 문제라는 걸 알게 됐다.
에러 — 코드가 실제로 터진다. 예외가 던져지고, 스택트레이스가 남고, 수집 도구를 붙이면 잡힌다.
조용한 어긋남 — 아무 데도 안 터지는데 값이 틀려 있다. 데이터끼리 안 맞거나, 가리키는 대상이 사라졌거나, 계산이 슬쩍 어긋났거나. 이건 찾으러 가야만 발견된다.
에러 수집 도구를 아무리 좋은 걸 붙여도 둘째는 하나도 못 잡는다. 반대로 데이터 점검을 아무리 촘촘히 짜도 첫째는 못 잡는다. 둘 다 필요한데, 나는 그때까지 둘 중 아무것도 없었다.
그래서 뭘 바꿨나
기록 테이블을 하나 만들고 둘을 같이 담기로 했다. 육하원칙을 칸으로 나눴다 — 언제(처음/마지막 발견) 어디서 누가 무엇을 어떻게 왜.
「왜」는 비워둘 수 있게 했다. 이번 것도 원인을 나중에야 알았기 때문이다.
그리고 자동 점검을 하나 짰다. 데이터베이스 사진 주소와 저장소의 실제 파일 목록을 대조하는 것. 손으로 돌려서 찾아낸 그 쿼리를 그대로 함수로 만들고, 하루 한 번 돌게 걸었다.
설계에서 제일 중요했던 건 중복을 막는 부분이었다
자동 점검은 돌 때마다 같은 걸 또 찾는다. 그대로 쌓으면 한 달이면 같은 항목이 수백 줄이 된다. 그리고 수백 줄짜리 목록은 아무도 안 본다. 그러면 감시 장치를 만들어놓고도 감시가 없는 것과 똑같아진다 — 애초에 이걸 만든 이유가 아무도 안 봐서 한 달 반 방치된 점이었는데 말이다.
그래서 항목마다 고유 키를 만들어, 이미 있으면 「마지막 확인 시각」과 횟수만 올리게 했다. 세 번 연달아 돌려봤더니 행은 2개 그대로고 횟수만 3으로 올랐다.
닫아둔 항목이 다음 점검에 또 나오면 자동으로 다시 열리게도 했다. 고친 줄 알았는데 안 고쳐진 경우가 있으니까.
화면 쪽도 손봤다. 사진이 깨지면 깨진 아이콘 대신 회색 자리가 뜨게. 다만 이건 증상을 가리는 쪽이라, 오히려 더 조용해진다. 그래서 점검이 짝으로 필요했다.