행인로 개인 작업실

선택자가 스스로 이상을 알리게 됐다

가격 수집기 하나가 하루 넘게 아무것도 못 가져온 적이 있다. 다른 글에서 이미 적었던 사건이다 — 대상 사이트가 프런트엔드를 통째로 바꿨고, “신규 수집 0건”이 아무 이상 없는 평범한 하루와 똑같이 보였다. 이유는 그게 오류로 취급되지 않았기 때문이다. 그 자리에서 파서만 고치는 건 쉬운 부분이었다. 더 어려운 질문은, 다음 프런트엔드 변경이 왔을 때 같은 침묵을 되풀이하지 않으려면 무엇을 만들어야 하느냐는 것이었다.

한 번만 울리고, 아예 안 울리지도 않는 경보

가장 순진한 해법 — 선택자가 아무것도 못 가져오면 무조건 경보를 울린다 — 에는 뻔한 실패 모드가 있다. 한 번 울리고는 그다음부터 매 회차마다 계속 울린다. 영원히 반복되는 경보는 한 번도 안 울리는 경보와 똑같이 무시당한다. 대신 넣은 건, 각 사이트 어댑터에 붙어 선택자가 기대한 모양과 개수를 계속 내고 있는지 지켜보는 작은 추적기다. 한 실행 안에서 같은 유형의 선택자가 어긋나면 딱 한 번, 태그가 붙은 경고 하나를 낸다 — 깨진 항목마다 한 줄이 아니라, 깨진 패턴마다 한 줄이다. 목표는 경고를 더 많이 내는 게 아니라, 예전에 아예 없던 자리에 읽을 수 있는 경고 하나를 두는 것이었다.

같이 들어간 조용한 변화가 하나 더 있다. 검증 단계는 원래 전부 아니면 전무였다 — 필드 하나라도 파싱에 실패하면 그 상품 항목 전체를 버렸다. 이제는 필수 필드와 선택 필드를 따로 판정한다. 선택 필드 하나가 빠지면 그 필드만 잃고 항목은 살아남는다. 필수 필드가 빠졌을 때만 항목 전체를 버린다. 가격 표기 형식 하나가 부분적으로 깨져도 이제는 데이터의 빈 칸으로 드러나지, 멀쩡하게 읽을 수 있었던 상품들이 통째로 사라지는 식으로 나타나지 않는다 — 이게 중요한 이유는, 이 버그의 첫 버전이라면 이번에도 파싱 문제가 아니라 그날 상품이 그만큼 줄어든 것처럼 보였을 것이기 때문이다.

일부러 망가뜨려서 폴백을 시험하다

파이프라인은 페이지를 가져오는 두 번째 방법도 갖게 됐다. 빠른 정적 페이지 요청이 쓸 만한 결과를 못 가져오면, 그냥 실패하는 대신 전체를 렌더링하는 방식으로 넘어간다. 이게 실제로 작동하는지 믿으려면 다음 실제 장애를 기다리는 대신 지금 확인해야 했다 — 그래서 예전에 아무도 눈치 못 챘던 바로 그 종류의 실패를 흉내 내려고 정적 요청 경로를 일부러 꺼봤다. 폴백은 매끄럽게 이어받았고, 약 2초 안에 같은 40건을 그대로 가져왔다.

재구축한 파이프라인으로 실제 상품을 다시 대조하다가 하나 더 발견했다. 상품 두 건이 광고 표식이 아예 없었고 기존 카탈로그 어디와도 매치되지 않았다 — 제 페이지가 없는 외부몰 연동 매물 단건으로, 가격도 사이트의 다른 모든 상품과 다른, 완전히 별개의 대체 필드에서 가져와야 했다. 수천 건 중 두 건, 작은 사례지만 정확히 검증된 폴백이 잡아내고 조용한 실패라면 그냥 놓쳤을 종류의 경계 사례다.

이 무엇도 다음 프런트엔드 변경을 막지는 못한다 — 그건 아무것도 약속할 수 없다. 달라진 건 변경이 일어난 다음 한 시간이다. 초록색 대시보드와 아무도 안 읽는 경고 대신, 이제는 어떤 패턴이 깨졌는지 말해주는 한 줄과, 포기하기 전에 다른 방법을 한 번 더 시도하는 요청 경로와, 부분적인 파싱 실패에도 함께 사라지지 않고 살아남는 레코드가 있다. 방금 발견한 바로 그 침묵을 위해 경보를 만들고, 그 침묵을 일부러 다시 일으켜 경보가 정말 울리는지 확인하는 것 — 그게 경보가 실제로 작동하는지 아는 유일한 방법이다.