Skip to content
게으른 엔지니어의 기술 블로그
Go back

배포 확인이 3번 다 실패라고 했는데, Cloudflare는 3번 다 성공이라고 했다

지난 글에서 “완료” 메일이 실제 배포 성공을 확인한 적이 없다는 걸 발견하고, push 후 실제 라이브 URL을 폴링해서 확인하는 로직을 추가했다. 오늘 아침, 그 로직이 만든 지 하루 만에 “배포 실패” 메일을 보냈다.

실패 메일을 받고 Cloudflare를 열어봤다

3번 다 확인 실패라고 했으니 뭔가 배포 자체가 안 됐나 싶어서 Cloudflare 대시보드를 열었다. 근데 오늘자 배포가 3개 다 성공으로 떠 있었다. 빌드 시간도 56초, 43초, 1분 13초 — 확인 로직이 기다리는 105초보다 전부 짧았다. 실제로 decipher99.com에 들어가봐도 오늘자 글이 멀쩡히 있었다.

첫 번째 의심 — 재시도가 빌드를 취소시켰나

확인이 실패할 때마다 빈 커밋으로 재push해서 재시도하는 로직도 같이 넣어뒀었다. 혹시 새 push가 들어올 때마다 Cloudflare가 진행 중이던 빌드를 취소하고 처음부터 다시 시작하는 거라면, 재시도 자체가 매번 거의 다 된 빌드를 취소시키는 역효과를 냈을 수 있겠다 싶었다. git log로 보니 커밋 3개가 3분 반 사이에 연달아 들어가 있어서 그럴싸한 가설이었다.

근데 Cloudflare 대시보드를 다시 확인해보니 3개 배포 전부 “취소”가 아니라 “성공”이었다. 이 가설은 틀렸다.

두 번째 의심 — 빌드가 예상보다 오래 걸렸나

그럼 그냥 105초가 부족했나 싶었다. 근데 실제 빌드 시간(56초/43초/73초)이 전부 105초보다 짧았다 — 이 가설도 데이터로 바로 반박됐다.

진짜 원인 — 확인 코드 자체가 차단당하고 있었다

배포도 제시간에 끝났고 취소되지도 않았다면, 남는 건 확인 코드 자신이었다. 실제로 확인 코드가 보내는 것과 똑같은 요청을 그대로 재현해서 실행해봤다. User-Agent를 따로 지정 안 하면 파이썬 표준 라이브러리는 Python-urllib/3.11 같은 기본값을 그대로 보낸다. 이 요청을 오늘자 글 URL로 그대로 보내보니 403 Forbidden이 돌아왔다. 똑같은 URL에 브라우저 User-Agent만 붙여서 보내니 200이 정상적으로 돌아왔다.

Cloudflare의 봇 방어가 Python-urllib라는 기본 서명을 그냥 차단하고 있었던 거다. 배포가 늦은 것도 아니고 취소된 것도 아니고 — 확인 요청 자체가 목적지에 닿기도 전에 막히고 있었다. 3번의 “실패”는 전부 배포 상태와 무관하게, 매번 같은 이유로 똑같이 막힌 결과였다.

아이러니

지난 글에서 만든 게 정확히 “확인 없이 완료라고 말하지 말자”는 로직이었는데, 그 확인 로직 자체가 검증 없이 배포된 새 코드였다. 심지어 이 문제를 이미 한 번 겪고 고친 코드가 같은 저장소 안에 있었다 — 기사 본문을 긁어오는 크롤러 코드는 진작부터 브라우저 User-Agent를 붙이고 있었다. 그 관례를 새로 짠 배포 확인 코드에는 그대로 안 옮겼을 뿐이다.

그때 짜둔 테스트도 다시 보니 전부 가짜 응답을 미리 정해두고 그걸로만 검증하는 것들이었다 — urlopen이 실제로 뭘 돌려줄지를 코드 안에서 직접 지정해두고, 그 지정된 값을 잘 처리하는지만 확인했다. 실제 Cloudflare에 단 한 번도 진짜로 요청을 보내본 적이 없었다.

고친 방식

크롤러가 이미 쓰고 있던 User-Agent 상수를 그대로 재사용하도록 고쳤다. 그리고 이번엔 이 문제가 조용히 재발하지 않도록, 확인 요청이 실제로 그 User-Agent를 달고 나가는지 확인하는 회귀 테스트를 추가했다.

남는 생각

가장 큰 문제는 첫 번째나 두 번째 가설이 틀렸다는 게 아니라, 애초에 그 지점까지 갈 필요가 없었다는 거다. 지난 글에서 이 확인 코드를 짜고 난 직후에, 실제 URL 하나를 상대로 딱 한 번만 진짜로 호출해봤다면 403이 그 자리에서 바로 나왔을 거다. 미리 정해둔 가짜 응답으로 로직만 확인하는 테스트는 “이 코드가 내가 생각한 대로 동작하는가”는 증명하지만, “이 코드가 실제 세상과 만났을 때도 그런가”는 증명하지 못한다. 돌다리도 두드려 보고 건너듯, 코드는 짜고 나면 실제로 한 번은 부딪혀봐야 한다 — 그 한 번을 건너뛴 대가로 잘못된 가설 두 개를 지우는 데 괜한 시간과 자원을 썼다.


Share this post:

Previous Part
메일 링크를 눌렀는데 404였다 — '완료'는 뭘 확인하고 보낸 걸까