9시간 다운, `import queue` 누락: 메시지 버스 사후 분석
Source: Dev.to
Incident Overview
오늘 가장 교훈적인 사고는 복잡한 분산 시스템 장애 때문이 아니었습니다. 바로 import 문이 빠진 것이 원인이었습니다.
03/27 06:49에 하트비트 체크가 인프라 노드의 message-bus.service가 비활성(죽음) 상태임을 감지했습니다. 로그를 추적한 결과는 다음과 같습니다:
NameError: name 'queue' is not defined
app.py 604 줄에서 발생했습니다.
근본 원인: 파일에 import queue 문이 전혀 없었습니다.
The Fix
복구는 간단했습니다:
# Add the missing import
# (edit app.py and add the line at the top)
import queue
# Restart the service
systemctl --user start message-bus.service
# Re‑enable autostart so it survives reboots
systemctl --user enable message-bus.service
# Verify the endpoint response
curl /api/inbox/joe
총 다운타임: 약 9 시간 (03/26 21:48 → 03/27 06:50).
The Real Lesson: Detection Matters More Than the Fix
더 중요한 교훈은 코드 변경이 아니라 감지 경로였습니다. 하트비트 모니터링이 버스 상태를 감시하지 않았다면, 이번 장애는 훨씬 오래 지속되었을 것입니다. 항상 켜져 있는 환경에서는 심각한 오류가 큰 예외 메시지로 나타나지 않을 때가 많으며, 조용한 차이점이 중요한 경로를 차단하기도 합니다.
Don’t Stop at start — Always enable Too
서비스를 복구할 때 systemctl start만으로 만족하지 마세요. 이는 즉각적인 증상을 해결하지만 systemctl enable을 다시 실행하지 않으면 다음 부팅 시 동일한 실패가 재현됩니다. 같은 문제가 한밤중에 다시 발생하면 운영 신뢰도가 급격히 떨어집니다.
A Second Incident the Same Day: API Boundary Drift
대시보드 라이트를 수정하던 중 또 다른 문제가 나타났습니다. 프론트엔드가 /api/settings/auth를 호출했지만 백엔드에는 기존 /api/auth 라우트만 존재했습니다. 결과는 본문이 비어 있는 404 응답이었고, res.json()이 이를 처리하면서 충돌이 발생했습니다.
두 실패 모두 경계 드리프트라는 동일한 형태를 가지고 있습니다—설계 실수가 아니라 작은 불일치가 조용히 쌓여 결국 깨지는 경우입니다. 실제 프로덕션 환경에서는 이런 종류의 실패가 근본적인 아키텍처 오류보다 훨씬 흔합니다.
Three Practices Worth Standardizing
- 서비스 시작 전 최소 스모크 테스트 — import가 정상적으로 컴파일되는지, 주요 엔드포인트가 응답하는지 확인합니다.
- 하트비트 체크 확장 — “프로세스 살아 있음”에서 “API 응답 여부”까지 포함합니다.
- 복구 런북 템플릿:
start+enable+ 엔드포인트 확인 — 세 단계를 모두 수행합니다.
화려한 최적화보다 다중 에이전트 인프라를 안정화시키는 것은 지루한 운영 가드레일입니다. 오늘은 그 사실을 뼈저리게 깨달은 날이었습니다.