WEBBOOK CHAPTER

Codex로 구축하는 AI 개발팀: 14장. 장기 작업과 실패 복구

14장. 장기 작업과 실패 복구

다음은 여러 현장에서 반복된 패턴을 합친 합성 사례로, 등장하는 숫자는 설명을 위한 예시 수치다.

대규모 마이그레이션 작업이 70% 진행된 밤, 실행 프로세스가 종료됐다. 다음 날 새 에이전트는 이전 대화를 읽을 수 없었다. 어떤 파일이 검증됐고 어떤 명령이 외부 시스템에 영향을 줬는지 몰라 처음부터 다시 시작했다. 일부 작업은 중복 수행됐고 결과를 신뢰할 수 없게 됐다.

장기 작업은 단지 타임아웃을 늘린 짧은 작업이 아니다. 기준선과 명세가 바뀌고, 프로세스와 도구가 실패하고, 문맥이 압축되며, 사람과 에이전트가 교대하는 것을 기본 조건으로 설계해야 한다.

이번 장의 약속

  • 장기 작업을 내구성 있는 단계와 체크포인트로 나눈다.
  • 재시작 가능한 계산과 한 번만 수행해야 할 외부 효과를 구분한다.
  • 임대 만료, 명세 변경, 부분 성공을 안전하게 복구한다.
  • 사람이 개입해도 인계 가능한 최소 상태를 남긴다.

대화가 아니라 상태를 지속한다

프로세스 메모리와 모델 문맥은 사라질 수 있다. 다음 상태를 외부의 내구성 있는 저장소에 기록한다.


작업·명세·기준선 버전
현재 단계와 완료한 단계
단계별 입력·출력 해시
도구 행동과 외부 효과 ID
게이트 결과
확정 사실과 폐기한 가설
남은 예산과 차단 이유
임대 소유자와 만료 시각
다음 안전 행동

체크포인트는 사람용 요약과 기계용 상태를 모두 가진다. Markdown handoff.md는 읽기 쉽고, JSON checkpoint.json은 재개 판정에 사용한다.

단계를 원자적 경계로 만든다

주문 총액 기능을 예로 들면:


S1 입력·명세 검증
S2 관련 코드와 계약 탐색
S3 도메인 변경
S4 빠른 게이트
S5 API 변경
S6 전체 게이트
S7 독립 리뷰
S8 통합 미리보기

각 단계는 다음 계약을 가진다.

설계 예(실행용 아님) — 원본: 이 장의 내구성 단계 설명; 명령: 없음.


{
  "step": "S4",
  "inputHashes": ["patch@...", "policy@..."],
  "status": "completed",
  "output": "gates/quick.json",
  "outputHash": "sha256:...",
  "sideEffect": "none",
  "completedAt": "2026-07-17T04:00:00Z"
}

재개 시 입력과 출력 해시가 같으면 완료 단계를 건너뛸 수 있다. 입력이 바뀌면 영향을 받는 단계부터 무효화한다.

멱등성과 중복 실행

분산 시스템에서는 완료 결과가 저장되기 직전에 프로세스가 죽을 수 있다. 제어면은 작업이 실행되지 않았는지, 실행됐지만 응답만 잃었는지 모른다. 따라서 외부 효과는 같은 키로 반복 요청해도 한 번의 논리 결과를 만들도록 설계한다.


idempotency key = taskId + stepId + inputHash

예를 들어 테스트 환경의 마이그레이션 요청이나 PR 생성 API에 이 키를 전달하고, 이미 성공한 키는 기존 결과 ID를 반환한다. 대상 시스템이 멱등성을 지원하지 않으면 실행 전 의도 기록과 실행 후 결과 조회, 사람 승인 같은 더 강한 경계를 둔다.

파일 쓰기는 임시 파일에 쓴 뒤 같은 파일시스템에서 원자적으로 교체하고 해시를 기록한다. 여러 파일의 원자성은 Git 커밋이나 단계별 작업 공간 봉인으로 다룬다.

외부 효과 장부

설계 예(실행용 아님) — 원본: 이 장의 외부 효과 장부 설명; 명령: 없음.


{
  "effectId": "ORDER-12:S8:abc123",
  "type": "create-change-request",
  "target": "repository/orders",
  "status": "confirmed",
  "requestHash": "sha256:...",
  "externalId": "change-441",
  "compensation": "close change request",
  "observedAt": "2026-07-17T04:20:00Z"
}

재개 실행은 먼저 장부와 외부 시스템을 조회한다. confirmed 효과를 반복하지 않는다. unknown은 자동 재시도하기 전에 영향과 조회 가능성을 확인한다.

보상은 되감기가 아니다

모든 외부 효과를 완전히 되돌릴 수는 없다. 이미 발송된 메시지는 회수할 수 없고, 공개된 비밀은 삭제해도 노출 사실이 남는다. 보상은 다음으로 일관성을 회복하는 새 행동이다.


생성한 임시 PR → 닫기
예약한 테스트 환경 → 해제
적용한 기능 플래그 → 이전 값으로 새 변경
노출한 자격 증명 → 폐기·회전·사건 조사

작업 계획 단계에서 각 외부 효과의 멱등성, 조회, 보상, 승인 소유자를 적는다.

체크포인트를 언제 만들까

  • 명세·설계 판단이 확정된 뒤
  • 비용이 큰 도구 호출이나 게이트 뒤
  • 외부 효과 전과 확인 뒤
  • 문맥 압축 전
  • 사람 승인이나 역할 교대 전
  • 작업 시간·행동 예산의 일정 비율마다
  • 종료·취소 신호를 받았을 때

너무 자주 저장하면 비용이 커지고, 너무 드물면 재작업이 커진다. 단계의 재실행 비용과 외부 효과 위험을 기준으로 정한다.

재개 알고리즘


1. 새 runId와 임대를 만든다.
2. 작업의 최신 명세·기준선·정책을 읽는다.
3. 마지막 유효 체크포인트의 해시와 서명을 확인한다.
4. 입력 변화가 영향을 주는 완료 단계를 무효화한다.
5. 외부 효과 장부와 실제 대상을 대조한다.
6. 작업 공간을 복원하거나 봉인된 patch를 새 공간에 적용한다.
7. 빠른 일관성 게이트를 실행한다.
8. 다음 미완료 안전 단계부터 계속한다.

이전 에이전트의 “거의 완료” 문장을 믿지 않고 산출물과 게이트를 확인한다.

명세와 기준선이 바뀌었을 때

명세가 그대로, 기준선만 전진

새 기준에 patch를 적용하고 영향 게이트를 다시 실행한다. 충돌이나 계약 변화가 있으면 BLOCKED_BASE_CHANGED로 계획을 검토한다.

명세가 호환되게 보강

새 수용 기준이 기존 결과에 영향을 주는지 추적하고 필요한 단계부터 재개한다. 명세 버전을 새 입력으로 기록한다.

명세 의미가 변경

기존 작업을 취소하고 새 작업 세대를 만든다. 이전 결과는 참고 산출물이지 자동 통합 후보가 아니다.

사람 개입의 세 형태

결정

모호한 제품·아키텍처 질문에 답한다. 결정 ID, 선택지, 근거, 영향을 기록하고 명세나 ADR에 반영한다.

수정

사람이 작업 공간의 코드를 직접 고친다. 수정 diff와 작성자를 이벤트로 남기고 이후 게이트를 다시 실행한다. ‘에이전트 100% 작성’ 같은 순도 지표보다 출처와 검증이 중요하다.

중단

위험·비용·우선순위 변화로 작업을 취소한다. 외부 효과와 임대를 정리하고 재개 가능 여부를 남긴다.

실습 1: 체크포인트를 남기고 이어받기


npm run demo:handoff
npm run demo:handoff 터미널. recoverable-change 시도 1이 체크포인트를 저장하고 시도 2가 재개해 GREEN으로 끝난다.
npm run demo:handoff 터미널. recoverable-change 시도 1이 체크포인트를 저장하고 시도 2가 재개해 GREEN으로 끝난다.

그림 14-1. 실제 인계 fixture는 첫 작업자의 체크포인트를 저장하고 두 번째 작업자가 남은 단계부터 재개한다.

중단 뒤 체크포인트 인계 보고서 화면. 상태 GREEN, 작업 1, 총 시도 2, 인계 1과 필수 게이트 결과가 보인다.
중단 뒤 체크포인트 인계 보고서 화면. 상태 GREEN, 작업 1, 총 시도 2, 인계 1과 필수 게이트 결과가 보인다.

그림 14-2. 같은 인계 실행의 보고서는 총 시도 2와 인계 1을 결과 증거와 연결한다.

첫 시도는 체크포인트를 남기고, 두 번째 시도가 같은 작업을 이어받습니다. 교육용 구현은 같은 프로세스에서 인계 흐름을 재현하며 새 runId를 발급하는 프로세스 재시작 기능은 약속하지 않습니다. 대신 서로 다른 attempt 작업 공간과 resumedFromHandoff 이벤트로 경계를 확인합니다.

확인할 항목:

  • 첫 시도와 두 번째 시도의 작업 공간 분리
  • .workspace.jsontaskId, attempt, baseline
  • 체크포인트의 completed, remaining, resumeHint
  • 두 번째 agent.invoked 이벤트의 resumedFromHandoff: true
  • 전체 게이트 최종 통과

현재 체크포인트는 폐기한 가설, 입력 해시, 외부 효과 장부를 저장하지 않습니다. 이 장 앞부분의 장기 작업 상태 모델은 실무 확장 목표이며, 예제는 완료/남은 일/재개 힌트의 최소 인계만 검증합니다.

실습 2: 충돌 창을 테스트로 설계합니다

현재 무API 예제는 실제 외부 변경 요청을 만들지 않으므로 ‘외부 호출 성공 뒤 확인 저장 전 프로세스 종료’를 구현했다고 주장하지 않습니다. 대신 다음 인수 테스트를 먼저 설계합니다.


given 같은 taskId·stepId·inputHash의 effectId
and 외부 대역에는 이미 externalId=change-441이 존재
and 로컬 장부 상태는 unknown
when 새 작업자가 효과를 재개
then 외부 대역을 조회해 change-441을 연결
and 생성 호출 횟수는 0

이 테스트를 통과하는 어댑터가 있을 때만 실제 외부 효과의 재개를 허용합니다. npm run demo:handoff는 파일 체크포인트 인계를 검증하지만 이 충돌 창을 대신하지 않습니다.

실습 3: 명세 변경의 기대 판정을 적습니다

먼저 현재 명세와 작업 스키마 검사를 실행합니다.


npm run check:specs
npm run check:tasks

그다음 별도 연습 복사본에서 체크포인트의 명세 버전을 3, 현재 승인 명세를 4로 둡니다. 예제의 현재 CLI는 이 시나리오 전용 명령을 제공하지 않으므로 다음 판정을 구현 과제로 삼습니다.


SPEC_CHANGED
old: SPEC-ORDER-007@3
new: SPEC-ORDER-007@4
affected: S3,S4,S5,S6,S7,S8
action: new task generation required

고착을 발견한다

프로세스가 살아 있어도 같은 파일과 테스트를 반복하며 진전이 없을 수 있다. 심박만으로는 알 수 없다.

진전 신호:

  • 새 게이트 결과 또는 실패 코드 변화
  • 남은 작업 수 감소
  • 확인된 사실·산출물 증가
  • patch 해시의 의미 있는 변화
  • 미결정 또는 위반 수 감소

같은 실패 코드와 유사 patch가 제한 횟수 반복되면 STALLED로 끝내고 사람 또는 다른 전략에 인계한다. 무한한 자기수정은 복구가 아니다.

왜 실패하는가

대화 전문만 저장한다

다음 실행이 공식 입력, 완료 단계, 외부 효과, 폐기한 가설을 안정적으로 추출하기 어렵다. 구조화된 체크포인트가 필요하다.

타임아웃 뒤 같은 작업 공간을 그대로 재실행한다

부분 변경과 프로세스가 남을 수 있다. 공간을 봉인·검사하고 새 임대에서 복원한다.

모든 단계를 다시 실행한다

비용이 늘고 외부 효과가 중복된다. 입력/출력 해시와 멱등 키로 안전한 완료 단계를 재사용한다.

상태를 ‘진행 중/완료’ 두 개로만 둔다

차단, 고착, 임대 손실, 오래된 결과, 외부 효과 불명이 구분되지 않는다. 대응 가능한 종료 이유를 가진다.

운영 판단: 장기 작업으로 허용할 조건

  • 단계별 입력·출력과 완료 증거가 정의됐다.
  • 체크포인트를 다른 실행이 검증하고 읽을 수 있다.
  • 외부 효과에 멱등 키, 조회, 보상 또는 사람 승인이 있다.
  • 임대 만료와 늦은 결과를 거부한다.
  • 명세·기준·정책 변경 시 무효화 규칙이 있다.
  • 고착과 예산 소진 뒤 안전하게 인계한다.
  • 민감한 장기 산출물의 접근·보존·삭제 정책이 있다.

연습문제

  1. 팀의 긴 작업 하나를 재시작 가능한 단계로 나누고 단계별 해시·외부 효과를 적어라.
  2. “API 호출이 성공했지만 응답을 받기 전에 죽음” 시나리오의 멱등/조회 정책을 설계하라.
  3. 기준 커밋 변경과 명세 의미 변경의 재개 정책 차이를 설명하라.
  4. 에이전트가 살아 있지만 고착된 상태를 검출할 진전 신호를 네 개 고르라.

체크포인트

  • 실행 프로세스 밖에 기계용 체크포인트와 사람용 인계가 있다.
  • 외부 효과는 멱등 키와 장부로 중복을 막는다.
  • 새 실행이 해시를 검증하고 안전한 단계부터 재개한다.
  • 명세 변경, 작업자 손실, 고착을 서로 다른 상태로 처리한다.

다음 장에서는 이 공장을 개인의 실험에서 팀의 표준 작업 방식으로 확장한다. 기술보다 먼저 책임, 도입 순서, 운영 소유권을 설계한다.