
exit code 0을 성공 판정으로 사용하지 않는 작업 설계 - 장애 분석
요약
프로세스의 종료 코드(exit code 0)를 성공의 절대적 기준으로 삼지 않고, 업무의 실제 상태를 구조화하여 관리하는 설계 방식을 제안합니다. 입력, 처리, 성과물, 공개 결과를 분리하여 장애 발생 시 정확한 지점에서 작업을 재개할 수 있는 메커니즘을 다룹니다.
핵심 포인트
- 프로세스 종료 코드(rc)와 실제 업무 상태(final_status)를 분리하여 설계
- 완료 조건을 생성, 품질, 조작, 결과의 4단계로 세분화하여 관리
- 자유 형식 로그 대신 구조화된 JSON을 사용하여 기계적 판단 가능하도록 구현
- 중간 정지 시 마지막 통과 단계를 기록하여 중복 실행 방지 및 재개 지점 확보
exit code 0을 성공 판정으로 사용하지 않는 작업 설계 - 장애 분석
자동 처리는 스케줄 등록만으로는 안정적이지 않습니다. 래퍼(Wrapper)가 정상 종료되더라도, 업무상의 결과는 보류·부분 완료·공개 실패일 수 있습니다.
이 기사에서는 「장애 분석」의 관점에서 입력, 처리, 성과물, 공개 결과를 분리하는 방법을 정리합니다. 메커니즘 전체의 이유까지 다룹니다.
기본 방침
업무 결과는 final_status로서 구조화하고, rc는 프로세스 분류용으로만 사용합니다.
프로세스가 종료되었다는 것과 목적을 달성했다는 것은 별개입니다. 초안 생성, 품질 검사, 외부 공개, 공개 URL 확인을 개별적으로 기록합니다. 상태를 분리함으로써, 다음 날의 처리를 추측이 아닌 증거를 바탕으로 재개할 수 있습니다.
구현 절차
rc=0/1/2와 업무 상태를 분리한다
성공 주장에는 성과물 경로를 필수 사항으로 한다
후속 단계에서는 rc보다 먼저 final_status를 읽는다
각 공정은 다음 공정이 기계적으로 판단할 수 있는 JSON을 출력합니다. 자유 형식 로그(Free-text log)에만 의존하면, 재실행 시 어디까지 완료되었는지를 인간이 추측해야 합니다.
result = {"rc": 2, "final_status": "CLEAN_HOLD_NO_CANDIDATE"}
assert result["final_status"] != "SUCCESS"
중요한 것은 코드의 양이 아니라, 입력과 결과의 계약(Contract)이 고정되어 있다는 점입니다. 성공뿐만 아니라 후보 부족이나 인증 대기 상태도 구조화하여 남깁니다.
완료 조건을 4단계로 분리
생성 완료: 본문, 메타데이터, 출처 정보가 존재함 -
품질 완료: 글자 수, 태그, 코드 예시, 중복 검사를 통과함 -
조작 완료: 허가된 runner가 대상을 한정하여 실행함 -
결과 완료: 실제 URL이나 외부 ID를 결과 파일로 확인함
중간 정지 시에는 마지막으로 통과한 단계와 다음 처리를 기록합니다. 처음부터 다시 시작하지 않고, 올바른 지점에서 재개할 수 있습니다.
자주 발생하는 실패
- 빈
rc=0이 공개 중단을 숨김 - 자유 형식 로그는 집계할 수 없음
- 재실행이 외부 처리를 중복시킴
재시도 횟수를 늘리기 전에, 어떤 상태라면 재시도가 가능한지를 결정합니다. 외부 공개 직전에는 당일 공개 여부, 제목과 본문 해시(Hash)가 신규인지, 대상 초안이 이번에 작성된 것인지 확인합니다.
테스트 관점
- 동일한 입력을 2회 처리해도 후보가 중복되지 않음
- 이미 공개된 제목을 후보로 선택하지 않음
- 본문 해시 충돌 시에는 다른 각도로 전환함
- 성과물이 누락된 경우에는 성공으로 처리하지 않음
- 외부 URL이 없는 경우에는 공개됨으로 기록하지 않음
- 재고가 7건 미만이면 게시 전에 보충함
일일 처리 구체적 예시
게시 시각을 10시 30분이라고 가정합니다. 2시 30분의 공급 처리에서는 단순히 Markdown 파일을 세는 것이 아니라, source_packet.json과 candidate_audit.json이 갖춰져 있고, 모든 품질 체크가 참(True)인 후보만을 미공개 재고로 계산합니다. 재고가 7건 미만이라면, 부족한 수만큼 다른 주제·각도를 선택하여 로컬에서 생성합니다. 이 단계에서는 외부 화면을 조작하지 않습니다.
10시 30분의 공개 처리에서는 재고의 맨 앞 1건을 선택합니다. 선택 후 공개된 제목과 정규화된 본문 해시를 다시 한번 읽습니다. 문제가 없다면 해당 후보로부터 하나의 초안 요청을 생성하고, 저장 결과에 포함된 제목과 초안 상태를 확인합니다. 공개 요청은 방금 생성한 동일한 초안만을 대상으로 합니다. 마지막으로 실제 URL에 도달했음을 결과 JSON에 저장하여 완료합니다.
이미지 생성에 실패한 경우, 본문 후보는 삭제하지 않습니다. cover_generation_failed로서 후보를 재고에 남깁니다. 인증이 만료된 경우에도 동일한 후보를 다시 만들지 않고 authentication_required로서 중단합니다. 공개 버튼 실행 후 확인 단계만 타임아웃된 경우에는, 다음 처리에서 외부 상태를 먼저 읽고 미공개임을 증명할 수 있을 때까지 재클릭하지 않습니다.
모니터링하는 수치
일일 모니터링에서는 다음을 별도로 기록합니다.
- 보충 전과 보충 후의 미공개 후보 수
- 새로 생성한 후보 수
- 제목 중복과 본문 중복으로 제외한 건수
- 외부 조작을 시작한 건수
- 실제 URL을 확인한 건수
- 마지막으로 통과한 공정과 정지 이유
「태스크가 기동된 횟수」만을 성공 지표로 삼으면, 후보가 0건인 상태로 매일 정상 종료되는 문제를 놓치게 됩니다. 공개 URL이 필요한 레인(Lane)에서는 실제 URL 확인 건수가 1이 되어야 비로소 일일 목표 달성으로 판단합니다.
재기동 후의 복구
재기동 후에는 메모리상의 상태가 아니라 파일 결과물로부터 재개합니다. 후보 감사가 완료되어 있다면 생성을 생략하고, 초안 저장 결과가 있다면 새로운 초안을 만들지 않습니다. 공개 결과에 실제 URL이 있다면 당일 처리를 종료합니다. 이 순서에 따라 PC 재기동이나 runner 정지가 발생하더라도, 외부 조작을 중복시키지 않고 계속 진행할 수 있습니다.
테스트에는 후보 0건, 손상된 JSON, 잔류 락(Lock), 공개 결과 없음 등을 포함합니다. 일일 운영에서 발생하기 쉬운 상황은 예외 상황보다 "처리는 끝났지만 목적물이 없는" 상태이기 때문입니다.
운영 체크리스트
- 입력원과 SHA-256이 기록되어 있음
- 제목과 본문의 중복 검사를 통과함
- provider와 action이 고정되어 있음
- 1일당 공개 상한을 초과하지 않음
- 결과 JSON에 실제 URL 또는 정확한 정지 이유가 있음
이러한 형태라면 후보 생산과 공개를 독립시키면서도 재고 수를 계약으로서 연결할 수 있습니다. 게시 시점에 후보가 없다면, 공급 공정을 실행한 후 재평가합니다.
관련된 실천 사례는 AI Compass Journal의 목록에서 확인할 수 있습니다.
Discussion

AI 자동 생성 콘텐츠
본 콘텐츠는 Zenn AI의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기