
도입부: “아침 9시, 뉴스가 오지 않았다”
2026년 4월 28일 화요일 아침. 평소라면 정확히 오전 6시에 텔레그램으로 도착해야 할 아침 브리핑 알림이 보이지 않았습니다. 처음에는 오늘도 바쁜 하루의 시작 전, 커피 한 잔과 함께 기다리고 있었는데요. 그런데 시간이 흘러도 조용했습니다.
그리고 그 다음 날, 수요일 아침까지 동일한 상황이 반복되었습니다. 이틀 연속으로 뉴스가 도착하지 않은 것이었죠.
자동화 시스템을 운영하는 분이라면 이런 경험 공감하실 겁니다. “아, 이번에도 무엇인가 깨졌구나.”
사태 분석: 무슨 일이 있었나
증상 기록
장애는 미묘하게 시작했습니다.
- 발생 시기: 2026년 4월 26일(일) ~ 4월 27일(월) 이틀간
- 예상 동작: 매일 오전 3시와 6시에 크론 잡이 실행되어 뉴스 수집 및 브리핑 생성
- 실제 동작: 크론 잡 히스토리에는 실행 기록이 남았으나, 의도한
briefing_YYYY-MM-DD.txt파일이 생성되지 않음 - 영향 범위: 텔레그램 아침 뉴스 브리핑 수신 중단
가장 이상한 점은 크론 자체는 “실행되었다”라고 기록하고 있었다는 것입니다. 즉, 파이프라인은 작동했는데, 최종 산출물이 없는 겁니다.
근본 원인 분석
로그를 파헤치고 메모리 파일을 살펴보며 원인을 추적해 보니, 다음과 같은 복합적인 문제들이 겹쳐 있었습니다.
| 원인 범주 | 구체적 내용 | 영향도 |
|---|---|---|
| 컨텍스트 손실 | news_editor 에이전트의 모델 변경/전환 과정에서 태스크 컨텍스트가 유실됨 | High |
| 크론 설정 누락 | 에이전트 업데이트 시 cron 작업 재설정이 누락됨 | High |
| 검증 미흡 | 배포 후 브리핑 파일 생성 여부 확인 프로세스 없음 | Medium |
특히 컨텍스트 손실이 핵심이었습니다. AI 에이전트는 모델이 변경되거나 재시작될 때, 메모리 외부에 저장되지 않은 실행 문맥을 잃어버릴 수 있습니다. 제 경우에는 generate_morning_news.py의 실행 경로나 환경 변수 설정 같은 “살아있는 상태”가 초기화되면서 파이프라인이 정상 가동하지 못했던 것이죠.
장애 복구 과정: 4단계 복구 시나리오
문제 해결은 단계별로 접근했습니다. 각 단계마다 명확한 검증 지표를 설정하고 진행했습니다.
1단계: 로그 분석 및 원인 규명
우선 /var/log/ 및 cron 로그를 확인했습니다.
# 크론 실행 이력 확인
grep "news_editor" /var/log/syslog | tail -20
Apr 26 03:00:01 server CRON[1234]: (user) CMD (/usr/bin/env python3 /root/.openclaw/workspace/skills/news-editor-agent/generate_morning_news.py 2026-04-26)
Apr 26 06:00:01 server CRON[1245]: (user) CMD (/usr/bin/env python3 /root/.openclaw/workspace/skills/news-editor-agent/generate_morning_news.py 2026-04-26)
# 실행은 되었으나 파일이 없음 확인
ls -la /root/.openclaw/workspace/news_editor/briefing_2026-04-26.txt
ls: cannot access 'briefing_2026-04-26.txt': No such file or directory
로그의 흔적은 있지만 산출물이 없는 상황. 즉시 수동으로 스크립트를 실행해 보니 예상대로 에러가 발생했습니다.
2단계: 크론 파이프라인 복구
원인을 파악한 후, 다음 항목들을 복구했습니다.
- 에이전트 런타임 환경 재설정
- 워킹 디렉토리 경로 명시적 지정
- 크론 잡에 환경 변수 전달 로직 추가
개선된 크론 설정은 다음과 같습니다.
# 크론탭 설정 (개선됨)
# 기존: 상대 경로 및 암묵적 환경 설정
0 3,6 * * * /usr/bin/env python3 /root/.openclaw/workspace/skills/news-editor-agent/generate_morning_news.py $(date +\%Y-\%m-\%d) >> /var/log/news_editor.log 2>&1
# 개선: 명시적 환경 변수 및 작업 디렉토리 설정
0 3,6 * * * cd /root/.openclaw/workspace/news_editor && /usr/bin/env python3 /root/.openclaw/workspace/skills/news-editor-agent/generate_morning_news.py $(date +\%Y-\%m-\%d) >> /var/log/news_editor.log 2>&1
cd를 명시적으로 추가하여 실행 컨텍스트를 확실히 고정했습니다.
3단계: 뉴스 수집 다양성 가이드 개선
장애 복구 중 발견한 또 다른 문제는 뉴스 키워드 선택의 편중이었습니다. 특정 키워드(예: “AI”, “IT”)에 과도하게 의존하여 다양한 소식을 놓치고 있었습니다.
이에 다음과 같은 개선을 적용했습니다.
- 채널별(국내/IT/게임/외신) 할당 키워드 다양화
- 검색 쿼리 로테이션 적용 (매일 다른 키워드 조합)
- 수집 결과 메타데이터 기록 (어떤 키워드로 어떤 기사가 선별되었는지)
4단계: 검증 프로세스 강화
마지막으로 “장애를 빨리 발견”할 수 있도록 검증 레이어를 추가했습니다.
- 발행일 검증: 수집된 기사의 발행일이 24시간 이내인지 확인
- 링크 유효성 검사: HTTP 200 응답 확인 스크립트 추가
- BRIEFING_READY 플래그: 파일 완성 여부를 명시적으로 표시하는 트레일러 라인 추가
검증 스크립트의 일부는 다음과 같습니다.
# validate_briefing.py
import os
from datetime import datetime
def validate_briefing(coverage_date):
filepath = f"/root/.openclaw/workspace/news_editor/briefing_{coverage_date}.txt"
# 1. 파일 존재 여부
if not os.path.exists(filepath):
return False, "파일이 존재하지 않습니다"
# 2. BRIEFING_READY 플래그 확인
with open(filepath, 'r') as f:
content = f.read()
if "BRIEFING_READY" not in content:
return False, "완성 플래그가 없습니다"
# 3. 크기 검증 (비어있거나 너무 작지 않은지)
if os.path.getsize(filepath) < 500:
return False, "파일 내용이 너무 적습니다"
return True, "검증 통과"
# 매일 오전 6:15에 검증 실행
# 15 6 * * * /usr/bin/env python3 validate_briefing.py $(date +\%Y-\%m-\%d)
교훈 및 개선안: 뼈저린 경험에서 배운 것
이번 사태를 통해 얻은 핵심 인사이트들을 공유합니다.
Graceful Degradation: AI의 예측 불가능성 대응하기
AI 에이전트는 편리하지만 "완전히 예측 가능한 상태를 유지하지는 않습니다". 모델 전환, 토큰 제한, 컨텍스트 창 관리 등 다양한 변수가 작동합니다.
핵심 원칙은 "에이전트의 불확실성을 인정하고, 외부 시스템으로 보완"하는 것입니다. 저는 이제 다음과 같은 fallback 메커니즘을 구축했습니다.
- 자동화 파이프라인 실패 시 수동 모드 전환 프로세스 문서화
- 블랙아웃 기간 알림 (뉴스가 2시간 이상 지연되면 경고)
- 메인 에이전트와 서브 에이전트 간 책임 분리 명확화
다중 에이전트 Orchestration 레이어의 중요성
현대 시스템에서는 단일 성공 경로를 믿지 않는 것이 중요합니다. 저는 이제 다음 레이어를 분리했습니다.
| 레이어 | 역할 | 에이전트 |
|---|---|---|
| 1. 수집/요약 | 뉴스 검색 및 요약 | news_editor |
| 2. 검증 | 품질 검사 및 컨텐츠 검증 | main |
| 3. 발송 | 텔레그램 전송 실행 | main/cron |
각 레이어는 독립적으로 실패할 수 있으면서도, 전체 프로세스는 계속 진행될 수 있도록 설계했습니다.
컨텍스트 관리의 핵심성
이번 장애의 핵심 원인은 "컨텍스트 손실"이었습니다. AI 에이전트는 상태를 메모리에만 저장할 경우 언제든 잃어버릴 수 있습니다.
"중요한 상태는 에이전트 외부에 저장하라. 메모리는 캐시이지, 저장소가 아니다."
따라서 치명적인 설정은 파일이나 환경 변수로 관리하고, 런타임에 명시적으로 로드하는 패턴을 채택했습니다.
모니터링과 관찰성(Observability) 강화
장애에서 가장 무서운 것은 "모르고 지나가는" 장애입니다. 그래서 다음을 추가했습니다.
- Heartbeat 패턴: 매일 오전 6시 브리핑 생성 후 "성공" 로그 기록
- 건강 체크 스크립트:
healthcheck스킬을 이용한 주기적 진단 - 알림: 검증 실패 시 즉시 텔레그램 경고 발송
마무리: 실전 체크리스트
다음은 독자분들께 바로 사용하실 수 있도록 정리한 체크리스트입니다. 자동화 파이프라인을 운영하시는 분들께 도움이 되길 바랍니다.
✅ 자동화 파이프라인 운영 체크리스트
- 배포 후 수동 실행 테스트를 통해 산출물 확인 여부 검증
- 크론 잡에 명시적
cd환경 명시 - 외부 종속(파일 경로, API 키, 환경 변수) 환경 설정으로 분리
- 중요 상태는 메모리 외 외부 저장소에 유지
- 실행 실패 시 fallback 프로세스 정의
- 출력 파일에 완성 플래그(예: BRIEFING_READY) 추가
- 결과 검증 스크립트 및 주기적 모니터링 설정
- 알림 메커니즘 구축 (성공/실패 모두)
- 장애 발생 시 수동 복구 절차 문서화
🚀 권장 도구 및 스킬
| 분야 | 도구/스킬 | 용도 |
|---|---|---|
| 검증 | Custom validator scripts | 산출물 품질 및 존재 확인 |
| 모니터링 | healthcheck skill | 주기적 시스템 상태 진단 |
| 데이터 수집 | tavily search | 신뢰할 수 있는 기사 수집 |
| 알림 | Telegram | 실시간 상태 알림 |
끝으로
이번 사태는 작은 자동화 시스템에서도 "잘 모르겠지만 작동하니까"라는 태도가 가져올 수 있는 리스크를 일깨워 주었습니다. 특히 멀티 에이전트 환경에서는 각 컴포넌트 간 경계를 명확히 하고, 상태 관리에 신중을 기해야 한다는 점을 다시 한번 깨닫게 되었습니다.
지금은 새벽 3시와 6시에 정상적으로 브리핑이 생성되고 있으며, 검증 스크립트도 매일 순조롭게 작동하고 있습니다. 작은 개선이 모여 큰 안정성을 만드는 법, 오늘도 그 과정을 배우고 있습니다.
혹시 비슷한 경험이 있으신 분이나, 자동화 파이프라인을 구축하시려는 분들께 이 글이 도움이 되었으면 합니다. 질문이나 피드백은 언제나 환영합니다!
본 포스팅은 실제 운영 경험을 바탕으로 작성되었습니다. 환경과 설정에 따라 적용 방식은 달라질 수 있습니다.
