새벽에 조용히 멈춘 자동화 — RSS·YouTube 35소스 자동 비활성과 언로드된 데몬
서킷브레이커가 달린 자동화의 "고쳤는데도 죽어 있는" 상태를 알아보고, 재활성 단계와 최소 감시를 체크리스트에 넣을 수 있어요.
공개일 · 갱신일
증상 원문
사이트 최신 기사가 7월 28일에서 멈췄다. 다이제스트는 매일 "empty → 발행 스킵"으로 끝났고, 빈 다이제스트가 18일 연속인데 알림은 한 건도 없었다. 그 앞 구간(7/4~7/28)은 더 헷갈렸다 — 발행은 됐지만 중복 미제거, 내부 URI 노출, 요약에 마크다운 원문 노출, "나머지 주요 뉴스" 빈 표였다.
8월 15일 초기 진단 — 두 겹으로 봤다
① 7월 4일, 소스 35개가 한꺼번에 자동 비활성화됐다. 스키마 드리프트 기간에 RSS·YouTube 소스 전부가 consecutive_failures=10에 도달해 is_active=f로 내려갔다. 마이그레이션은 이후 수리됐지만 재활성화는 아무도 하지 않았다. 자동 비활성은 sticky해서 원인이 사라져도 스스로 돌아오지 않는다.
② 7월 28일 20:33, 채팅 수집 데몬이 언로드됐다. 자동 실행 목록에 plist가 없었다(저장소에는 있었다). 이때 진단은 ①이 만든 "채팅 전용 다이제스트"를 ②가 끊었다는 것이었다.
최종 설명 — 8월 16일에 ②가 뒤집혔다
다음 날 확인된 사실은 달랐다. 실제 운영 수집기는 그 데몬이 아니라 30분 주기 corpus-refresh의 백필 스크립트였고, 7월 28일 언로드는 의도된 은퇴였다. 수집이 멈춘 진짜 이유는 더 위에 있었다 — 메신저 맥 클라이언트가 7월 28일 20:06 이후 메시지를 아예 수신하지 않았다. 데몬을 되살려도 받을 것이 없었다.
잘못된 복구 시도
8월 15일 복구에서 은퇴한 데몬의 plist를 설치해 되살린 조치가 2차 사고를 불렀다. 발신자 해석이 비결정적이 되면서 UNIQUE 제약을 우회했고, 재주행마다 약 275,000건이 재삽입됐다(2회 발생, 2회 모두 백업 후 정리).
고친 방법
- RSS 32개 소스 재활성 — 첫 사이클 503건 수집. (35개 중 32개만 재활성한 이유는 기록에 남기지 않았어요.)
- 스텁 발행 경로를 실제 산출물 발행으로 교체.
- 3건 미만 게이트 + 연속 스킵 워치독을 알림으로 배선. 발행 실패 자체도 감지 대상에 넣었다.
- 8월 15일 다이제스트 19건 실발행으로 검증.
- 2차 사고 수습(8월 16일): 되살린 데몬을 다시 은퇴시키고, 발신자 해석을 방 스코프의 결정적 질의로 고치고, 오염분을 백업 후 정리한 뒤 재실행으로 멱등성을 확인했다.
- 메신저 클라이언트 재로그인은 후속 작업으로 남았다. 채팅 경로의 정상 수신 복구까지 끝났다는 근거는 없다.
재발 방지
교훈은 다음과 같아요.
- 자동 비활성화가 있는 시스템은 장애 수리 후 "재활성" 단계가 체크리스트에 없으면 조용히 죽은 채 남아요. 수리 완료와 복구 완료는 다른 항목이에요.
- 산출량 0이 N일 연속이면 알리는 최소 감시부터 거세요. 18일이 그냥 지나간 이유는 아무도 0을 보고 있지 않았기 때문이에요.
- 워치독은 "재료 부족"만이 아니라 발행 실패 자체를 봐야 해요. 성공 응답 안의
ok:false까지 확인해요. - 멈춘 부품을 되살리기 전에 그게 아직 현역인지 확인해요. 은퇴한 경로를 복구로 착각하면 복구가 2차 사고가 돼요.
실행일·도구 버전
진단 2026-08-15, 정정·2차 수습 2026-08-16. 사용한 도구 버전은 기록에 남기지 않았어요. 재현할 때는 현재 버전을 기준으로 확인하세요.
근거
- 운영 메모리 ai-news-pipeline-outage-202608 (2026-08-15~16 진단 기록 전문)