티스토리 뷰
목차
4개 블로그의 글감을 매일 골라주는 프로그램이 있다.
이름은 소재 레이더, 정체는 /d/hotkeywords/topic_radar.py라는 코드 한 덩어리다.
이 레이더를 돌릴 때마다 마지막에 HTTPError 400이 찍히고 그대로 멈췄다.
에러만 찍히고 끝나는 게 아니라, 그날 글감 후보 파일 자체가 아예 만들어지지 않았다.

레이더가 계속 "채택 없음"이었던 게 아니라, 아예 안 돌고 있었다
처음엔 그냥 요즘 글감이 다 비슷비슷해서 "채택할 게 없다"고 나오는 줄 알았다.
최근 며칠 기록을 보면 제미나이·클로드 쪽 키워드가 겹쳐서 실제로 그런 날도 있었기 때문이다.
그런데 이번엔 달랐다. 파일 생성 자체가 안 됐다.
"채택 없음"이면 적어도 빈 결과 파일은 남는데, 이번엔 결과 파일 자체가 통째로 없었다.
처음엔 자기잠식 판단 로직을 의심했다
솔직히 처음엔 키워드 클러스터링이나 자기잠식 판단 쪽 로직이 어딘가 꼬였나 싶었다.
최근 2주 가까이 같은 주제(제미나이·클로드)가 상위권을 채우던 전례가 있어서 그쪽부터 들여다봤다.
그 부분은 멀쩡했다. 로직이 아니라 그보다 훨씬 앞단, 검색량을 조회하는 단계에서 전체가 죽고 있었다.
내가 코드를 처음부터 끝까지 다시 읽은 건 그래서였다.
원인은 청크 안에 섞인 외국어 한 단어였다
문제의 함수는 run_blog()다. 구글 급상승 검색어와 자동완성 변형을 모아 네이버 광고 API(키워드도구)에 던져 월간 검색량을 묻는 역할을 한다.
이 API는 키워드를 5개씩 묶어서(청크) 한 번에 조회한다.
그런데 그 5개짜리 묶음 중 하나에 한글이 전혀 없는 외국어 구문이 끼어 있었다.
실제 사례는 베트남어 "thời tiết ngày mai"(내일 날씨라는 뜻)였다. 구글 급상승 자동완성에 어쩌다 섞여 들어온 거였다.
이 외국어 하나가 청크에 들어가면, 네이버 API가 그 청크 전체를 400으로 거부해버렸다.
같이 묶인 멀쩡한 한글 키워드 4개까지 전부 조회가 안 됐고, 결국 topic_radar.py 전체가 예외로 죽으면서 레이더 파일 자체가 생성되지 않았다.

당황스러웠던 건 이 레이더가 4개 블로그 전부 같은 함수를 탄다는 점이었다.
1·3·4호 블로그도 같은 시점에 공통 장애였을 것으로 보인다 — 다만 이건 추정이고, 블로그별 로그를 따로 대조해서 확인한 사실은 아니다.
| 청크(5개 키워드 묶음) 상태 | 실제로 벌어진 일 |
|---|---|
| 5개 전부 한글 키워드 | 정상 조회, 검색량 반환 |
| 4개 한글 + 외국어 1개 | 청크 전체 400 거부 — 멀쩡한 4개도 같이 조회 실패 |
| 전체 실행 결과 | 예외 발생 → topic_radar.py 중단 → 레이더 파일 미생성 |
한 줄 필터로 고쳤다
고치는 데 긴 코드가 필요하진 않았다. run_blog()에서 검색량 조회 직전에 한 줄을 추가했다.
# 2026-10-05: 외국어 전용 키워드(예: 구글 급상승에 섞여 들어온 베트남어 "thời tiết ngày mai")가
# 네이버 광고 API에 들어가면 그 chunk 전체가 HTTP 400으로 죽어 레이더가 통째로 중단된다.
# 한글이 한 글자도 없는 후보는 이 블로그 체계상 쓸 일이 없으므로 조회 전에 제거한다.
kws = [k for k in kws if re.search(r"[가-힣]", k)]
한글이 한 글자도 없는 후보는 아예 조회 목록에서 빼버리는 코드다.
이 블로그들은 전부 한글 검색 키워드만 다루니, 외국어 후보는 처음부터 조회할 이유가 없었다.

수정 후 다시 돌리니 바로 성공했다. 그날(10월 5일) 레이더가 44건을 만들어냈다.
오늘(10월 7일) 레이더도 20건이 정상 생성된 걸 직접 확인했다 — 그 한 줄이 지금도 매일 밤 조용히 일하고 있다는 뜻이다.
API 호출이 이유 없이 통째로 죽을 때 확인할 순서
① 에러 메시지(400 등)가 "요청 자체가 이상하다"는 뜻이면, 요청 건수가 아니라 요청 묶음(청크) 안의 내용을 하나씩 의심한다.
② 여러 항목을 한 번에 묶어 보내는 API라면, 묶음 중 하나라도 비정상이면 묶음 전체가 거부될 수 있다는 걸 가정하고 로그를 묶음 단위로 쪼개 본다.
③ 자동 수집 데이터(자동완성·급상승 검색어 등)는 예상 밖의 값(외국어, 특수문자)이 섞여 들어올 수 있다 — 조회 전에 형식을 한 번 걸러낸다.
④ 같은 함수를 여러 곳에서 공유한다면, 한 곳의 장애가 전부에 영향을 줬을 가능성을 함께 적어두되 실제 확인 전까지는 추정으로 남겨둔다.
이런 "겉보기엔 고장 신호가 없는" 사고는 이번이 처음이 아니었다.
예전엔 무인 배치가 질문만 던지고 멈춰버린 자동화 시스템 오류 사고가 있었고, 다른 자동화가 포트를 가로채 아침 제작이 시작도 못 한 포트 충돌 자동화 사고도 있었다. 원인이 토큰 재발급 구조에 있었던 텔레그램 봇 401 오류 사고도 같은 운영 기록 시리즈다.
자주 묻는 질문
Q1 소재 레이더가 정확히 뭔가
4개 블로그의 그날 글감 후보를 점수 매겨 추천해주는 내부 프로그램이다.
사람이 매번 검색해서 고르는 대신 이 프로그램이 매일 밤 후보 목록을 만들어둔다.
Q2 왜 에러 로그만 봐서는 원인을 못 찾았나
에러 자체는 요청이 400으로 거부됐다는 한 줄뿐이었고, 어떤 키워드 때문인지는 로그에 안 찍혔다.
코드를 직접 열어 묶음 단위로 보내는 구조를 확인해야 범위가 좁혀졌다.
Q3 같은 증상을 겪으면 뭐부터 확인해야 하나
항목을 묶어서 보내는 API를 쓰고 있는지부터 본다.
묶여 있다면 묶음 하나가 비정상이어도 전체가 거부될 수 있으니, 자동 수집 데이터는 형식 검증을 조회 전에 먼저 넣는 게 맞다.