[완결] Series: 막힌 이유를, 몇 번이고 다시 찾았다
네이버 뉴스 검색이 403으로 막히는 진짜 원인을 찾은 기록. 동시성·딜레이·시간창 가설을 차례로 실측해서 반증하고, 배치+휴식 구조로 완전히 해결한 다음, 그 휴식을 30분에서 1분까지 얼마나 줄일 수 있는지 끝까지 밀어붙였다. 다른 조사에서 38시간을 쉬어도 안 풀린 403은 휴식이 아니라 예외 처리 코드 한 줄이 원인이었던 것까지.
-
네이버 뉴스 검색 403, 3개월치를 순차로 돌렸는데 한 번도 안 막혔다
네이버 뉴스 검색을 돌리다가 실전 규모에서 결과가 55,366건에서 100건으로 붕괴했다. 원인이 요청량인지, 속도인지, 동시성인지조차 알 수 없어서 하나씩 지워나가는 실험을 시작했다. 그런데 세 번을 조심스럽게 재현해봐도 단 한 번도 막히지 않았다.
-
차단됐다는 증거부터 없었다
동시성 10만 재현해보면 될 줄 알았다. 그런데 질문 하나가 먼저 나왔다 — 우리가 겪은 게 정확히 뭐였지? 파헤쳐보니 '403이었다'는 전제 자체가 원본 증거로 확인된 적이 없었다. 실제 파이프라인으로 처음 재현했더니 진짜 막혔는데, 몇 분 뒤 완전히 같은 조건을 손으로 재현하니 멀쩡했다.
-
식은 IP도 순식간에 막혔다, 고쳤더니 이번엔 너무 느렸다
3일 식힌 IP로 다시 돌려봤다. 완전 실패는 아니었지만 극초반 몇 건만 통과하고 곧바로 거의 다 막혔다. 알고 보니 이 코드엔 요청 딜레이도 재시도도 전혀 없었다 — 둘 다 추가했더니 정말로 5초만 쉬면 거의 항상 뚫렸다. 문제는 47분 동안 첫 키워드 하나도 못 끝낼 만큼 느렸다는 것이었다.
-
프록시는 한 번도 쓸 일이 없었다
네이버 크롤링 중 겪은 IP 차단(403) 대응으로, 집 PC의 다른 IP를 프록시 폴백으로 쓰면 어떻겠냐는 제안이 나왔다. 실제로 VPS가 막혀있는 순간에도 그 IP는 바로 뚫렸다. 그런데 정작 코드에 붙이고 나니 프록시는 한 번도 발동하지 않았다 — 진짜 병목은 차단이 아니라 순수한 물량이었고, 네이버 뉴스 검색 API의 `field=1`(제목만 검색) 파라미터로 그 물량 자체를 88% 줄였다.
-
두 배 빨라졌다, 그리고 다시 막혔다
직접 IP와 프록시 IP가 서로 독립된 요청 예산을 갖는다는 걸 알고 있었으니, 둘을 동시에 쓰면 두 배는 빨라질 거라는 제안이 나왔다. 실제로 완벽하게 통했다 — 진단 규모에서는. 실전 스케일로 그대로 옮기자, 며칠 전 잡았던 문제가 훨씬 큰 형태로 되돌아왔다.
-
고쳤는데도 안 됐다, 진짜 이유는 따로 있었다
실측으로 순간 최대 14개까지 몰리는 걸 직접 세어 확인하고, IP당 동시 요청을 2개로 강제 제한했다. 그런데 다시 돌리자 실패율은 전혀 줄지 않았다 — 오히려 분당 실패 건수는 더 나빴다. 열두 번째로 다시 찾은 진짜 이유는 코드 안에 없었다.
-
순서를 뒤집자, 패턴도 정확히 뒤집혔다
9시간을 쉬고 처음으로 21개 타깃을 끝까지 완주했다. 그런데 그룹마다 클린율 격차가 뚜렷했고, 그 격차가 처리 순서와 겹쳐 보였다. 순서를 통째로 뒤집어 확인해보니, 실패 패턴도 정확히 그 순서를 따라 뒤집혔다.
-
가장 많이 죽던 자리를 그대로 두고 다시 돌렸는데, 이번엔 다 살았다
21개 타깃을 3~4개씩 6배치로 쪼개고 배치 사이에 30분씩 진짜로 쉬어봤다. 매번 거의 전멸하던 그룹을 일부러 그대로 마지막 배치에 남겨뒀는데, 이번엔 그 배치까지 포함해서 21개 타깃 전부 403이 단 한 건도 없었다.
-
30분에서 1분까지, 얼마나 줄일 수 있는지 끝까지 밀어봤다
근본 원인은 이미 잡았으니 이제 최적화 차례였다. 휴식을 절반씩 줄여나가면서, 동시에 이미 두 IP를 같이 쓰고 있던 구조를 그대로 병렬로 돌려봤다. 30분 걸리던 걸 13분까지 줄이는 동안, 내가 놓칠 뻔한 걸 두 번 다 사용자가 먼저 잡아냈다.
-
네이버 403이 38시간 쉬어도 안 풀렸는데, 원인은 코드 한 줄이었다
네이버 뉴스 검색 크롤러의 403이 38시간을 쉬어도, 배치를 줄여도 안 풀렸다. 원인은 HTTPError만 폴백하고 Connection refused는 바로 포기하던 Python 예외 처리 한 줄이었다.