WEBBOOK CHAPTER

Codex로 구축하는 AI 개발팀: 7장. 작업을 그래프로 쪼갠다

7장. 작업을 그래프로 쪼갠다

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

“주문 총액 기능을 구현하라”는 작업을 세 에이전트에게 병렬로 보냈다. 한 에이전트는 도메인 계산을 만들었고, 한 에이전트는 API 필드를 추가했으며, 다른 에이전트는 테스트를 작성했다. 모두 자기 작업은 끝났다고 보고했다. 통합하자 API가 다른 함수명을 호출했고 테스트는 세 번째 계산 규칙을 기대했다. 병렬로 일했지만 공통 계약과 의존 순서가 없었다.

작업 분해의 목적은 에이전트를 바쁘게 만드는 것이 아니다. 각 변경이 작은 증거를 만들고, 서로의 가정을 명시하며, 안전하게 합쳐질 수 있게 하는 것이다.

이번 장의 약속

  • 기능을 파일 목록이 아닌 검증 가능한 결과로 나눈다.
  • 작업 의존성을 방향성 비순환 그래프로 표현한다.
  • 충돌 가능성과 결합 비용을 보고 병렬 실행을 선택한다.
  • 준비, 완료, 차단 상태를 기계가 판정하게 한다.

좋은 작업의 여섯 속성

에이전트에 보낼 작업은 다음을 가진다.

  1. 하나의 관찰 가능한 결과: 완료 뒤 무엇이 달라지는가?
  2. 작은 변경 경계: 어느 모듈과 경로를 소유하는가?
  3. 명시적 입력: 명세 버전과 선행 산출물은 무엇인가?
  4. 독립 판정: 어떤 게이트로 이 작업만 검증하는가?
  5. 제한된 불확실성: 사람의 제품 판단이 남아 있지 않은가?
  6. 인계 가능한 상태: 실패해도 시도와 다음 행동을 남기는가?

작업 크기의 절대 기준은 없다. 한 파일보다 작아도 제품 의미가 불완전할 수 있고 열 파일을 바꿔도 하나의 원자적 마이그레이션일 수 있다. 리뷰어가 변경의 목적과 증거를 한 번에 이해하고, 실패 시 폐기하거나 되돌릴 수 있는 범위가 실용적인 기준이다.

수평 층보다 얇은 수직 조각

다음 분해는 역할별로 편하지만 각 작업이 독립 가치를 증명하기 어렵다.


A: 모든 도메인 모델 작성
B: 모든 API 작성
C: 모든 테스트 작성

가능하면 작은 기능 흐름으로 나눈다.


A: 단일 주문의 총액 규칙 + 단위 증거
B: 주문 조회 응답 계약에 total 추가 + 계약 증거 (A 의존)
C: 취소 품목 예외 + 회귀 증거 (A 의존)
D: 목록 성능 게이트 + 기준 측정 (B, C 의존)

각 작업은 제품 규칙의 일부를 끝까지 닫고, 다음 작업이 사용할 계약을 낸다. 단, 공통 스키마나 마이그레이션처럼 실제 의존성이 있는 기반 작업을 억지로 중복하지 않는다.

작업 계약

설계 예(실행용 아님) — 원본: 이 장의 현장용 작업 봉투 설명; 명령: 없음.


{
  "id": "ORDER-12",
  "title": "주문 조회 응답에 total을 추가한다",
  "spec": { "id": "SPEC-ORDER-007", "version": 3 },
  "outcome": "GET /orders/:id 응답이 AC-01~03을 만족한다",
  "dependsOn": ["ORDER-11"],
  "inputs": ["artifacts/ORDER-11/domain-contract.json"],
  "allowedPaths": ["src/orders/api/", "test/contracts/"],
  "forbiddenPaths": ["factory/", ".github/"],
  "requiredGates": ["contract", "architecture", "secrets"],
  "risk": "medium",
  "maxAttempts": 3
}

outcome은 “코드를 작성한다”가 아니라 외부에서 확인할 결과다. 선행 작업 ID만 쓰지 않고 소비할 산출물을 명시하면 결합점이 보인다.

의존 그래프

작업은 노드, 의존성은 방향 간선이다.


ORDER-10 명세 검증
   └──> ORDER-11 도메인 총액
          ├──> ORDER-12 API 계약 ──┐
          └──> ORDER-13 취소 예외 ─┼──> ORDER-15 통합 시나리오
ORDER-14 성능 기준선 ───────────────┘
ORDER-10 명세 검증에서 ORDER-11 도메인 총액으로 이어지고, ORDER-11에서 ORDER-12 API 계약과 ORDER-13 취소 예외로 갈라져 ORDER-15 통합 시나리오로 합쳐지며 ORDER-14 성능 기준선도 ORDER-15에 연결되는 DAG.
ORDER-10 명세 검증에서 ORDER-11 도메인 총액으로 이어지고, ORDER-11에서 ORDER-12 API 계약과 ORDER-13 취소 예외로 갈라져 ORDER-15 통합 시나리오로 합쳐지며 ORDER-14 성능 기준선도 ORDER-15에 연결되는 DAG.

그림 7-1. ORDER-12와 ORDER-13은 공통 선행 계약 뒤 병렬 후보가 되며, ORDER-15는 필요한 증거를 모두 기다린다. 이 그림은 설계 원리를 설명하는 예이며 실습 JSON의 실제 작업명은 아래에서 따로 확인한다.

그래프는 순환하면 안 된다. A가 B를 기다리고 B가 A를 기다리면 어떤 작업도 준비되지 않는다. 순환은 대개 작업 경계 또는 공개 계약이 불명확하다는 신호다. 공통 계약을 앞선 작은 작업으로 분리하거나 두 작업을 하나의 원자 작업으로 합친다.

준비 상태는 느낌이 아니라 조건이다

작업이 READY가 되려면 다음을 모두 만족한다.


승인된 명세 버전이 존재한다.
필수 선행 작업이 성공했다.
선행 산출물의 해시가 일치한다.
허용 경로와 필수 게이트가 정의됐다.
위험 수준에 필요한 승인이 있다.
동일한 소유 경계에 실행 중인 충돌 작업이 없다.

대기 이유를 코드로 기록한다.


WAITING_DEPENDENCY
WAITING_SPEC_APPROVAL
WAITING_RISK_APPROVAL
WAITING_OWNERSHIP

모두 pending으로 표시하면 병목을 알 수 없다.

병렬성은 독립성에서 나온다

두 작업을 병렬로 실행할 수 있는지 세 층에서 검사한다.

데이터 의존

B가 A의 생성 스키마나 결정을 사용하면 순차다. 인터페이스를 먼저 확정해 두 작업이 같은 계약을 읽을 수 있다면 병렬화할 수 있다.

변경 집합 충돌

허용 경로가 겹치거나 공통 설정·잠금 파일을 바꾸면 충돌 가능성이 크다. 예상 변경 집합과 실제 변경 집합을 모두 기록해 분해 정확도를 개선한다.

의미 충돌

파일이 달라도 같은 제품 규칙을 서로 다르게 구현할 수 있다. 도메인 계산과 UI 표시가 각자 반올림 규칙을 선택하는 경우다. 공통 명세와 계약 테스트가 의미 충돌을 줄인다.

간단한 충돌 행렬을 만든다.

작업 ORDER-11 ORDER-12 ORDER-13 ORDER-14
ORDER-11 의존 의존 낮음
ORDER-12 의존 API 파일 가능 낮음
ORDER-13 의존 API 파일 가능 낮음
ORDER-14 낮음 낮음 낮음

‘낮음’은 0이 아니다. 실제 충돌 데이터를 기록해 다음 계획의 추정에 반영한다.

병렬화 이득을 계산하는 경험칙

병렬 실행의 기대 이득을 다음처럼 생각할 수 있다.


순이득 = 줄어든 대기 시간
       - 격리/시작 비용
       - 충돌 확률 × 충돌 해결 비용
       - 동시 리뷰와 관측의 추가 비용

정확한 예측 공식이 아니라 누락하기 쉬운 비용을 드러내는 틀이다. 3분짜리 작업 두 개를 컨테이너로 각각 준비하는 데 2분이 든다면 병렬화가 이득이 아닐 수 있다. 2시간짜리 독립 테스트 생성 작업은 충분한 가치가 있다.

에이전트가 계획하고 하니스가 검증한다

모델은 요구를 작업 후보로 나누는 데 유용하지만 자신의 계획을 스스로 승인하게 하지 않습니다. 운영용 계획 검증기의 목표 범위는 다음과 같습니다.

  • ID 중복과 순환 의존성
  • 존재하지 않는 명세·게이트·산출물 참조
  • 지나치게 넓거나 금지된 허용 경로
  • 선행 결과 없이 소비되는 산출물
  • 완료 조건 없는 작업
  • 고위험 작업의 승인 누락

사람은 제품 경계, 소유권, 의미 충돌, 위험 수준을 검토한다.

현재 교육용 loadSpec이 구현한 범위는 ID·시도 한도·작업 연산·안전한 경로·존재하는 의존성·순환 방지입니다. 넓은 권한, 고위험 승인, 산출물 의미 계약은 개념 설명과 확장 과제이며 현재 검사기가 이미 판정한다고 주장하지 않습니다.

실습: 설계 DAG를 실제 캡스톤과 비교한다

1단계: 완료 결과부터 뒤로 간다

최종 결과는 “주문 조회 API가 승인된 총액 규칙과 호환성 기준을 만족한다”다. 필요한 증거를 적는다.


도메인 규칙 단위 테스트
API 계약 테스트
취소/오류 회귀 테스트
구조 검사
성능 비교
독립 리뷰

2단계: 증거를 만드는 작업을 만든다

각 작업이 증거 하나 이상을 완성하도록 나눈다. ‘테스트만 나중에’라는 별도 꼬리를 만들지 않는다.

3단계: 소비 계약을 적는다

API 작업이 도메인 작업에서 필요한 것은 코드 전체가 아니라 공개 함수와 금액 타입이다. 이를 domain-contract.json 같은 산출물로 표현한다.

4단계: 실제 JSON 검사


npm run check:tasks

이 명령은 tasks/의 JSON 세 개를 각각 로드해 스키마, ID, 시도, 연산, 출력 경로, 존재하는 의존성과 순환을 검사합니다. 현재 구현은 작업 사이의 예상 경로 겹침을 경고하지 않습니다. 겹침 검사는 specs/conflict.json의 실제 통합 충돌 fixture에서 별도로 확인합니다.

5단계: 준비된 작업만 보기


npm run queue -- --status ready

명시하지 않으면 이 명령은 specs/capstone.json을 읽습니다. 실제 기대 출력은 다음과 같습니다.


명세: specs/capstone.json
상태: ready
작업 2개
- domain-model
- reader-docs

교육용 queue CLI는 실행 중 상태를 지속적으로 추적하는 운영 큐가 아니라, 아직 아무 작업도 완료되지 않은 시작 시점에 dependsOn이 빈 작업을 보여 주는 읽기 도구입니다. 다음 작업의 동적 해제는 npm run demo의 실제 배치 이벤트에서 확인합니다.

실습 캡스톤의 실제 DAG는 다음과 같습니다.


domain-model ─→ repository-adapter ─→ order-service ─→ order-demo
reader-docs  (독립)

order-servicedomain-modelrepository-adapter, order-demoorder-servicerepository-adapter를 기다립니다. ORDER-10~15 예시는 이 실제 JSON을 가장한 화면이 아니라 더 복잡한 현장 설계를 연습하기 위한 모델입니다.

동적 재계획

작업 중 예상과 다른 공개 계약 변경이 필요할 수 있다. 에이전트가 후속 작업 파일을 몰래 고치게 하지 않는다.

  1. 현재 작업을 BLOCKED로 끝낸다.
  2. 발견한 사실과 필요한 계약 변경을 인계 문서에 남긴다.
  3. 계획 변경 제안을 별도 산출물로 만든다.
  4. 영향받는 하위 그래프를 계산한다.
  5. 승인 뒤 작업 버전을 올리고 영향 작업을 다시 준비한다.

이미 실행 중인 하위 작업의 입력 해시가 바뀌면 결과를 자동 통합하지 않는다. 취소하거나 새 명세와의 호환을 별도 검증한다.

왜 실패하는가

작업을 파일 단위로만 나눈다

에이전트끼리 파일 충돌은 줄지만 제품 규칙의 통합 책임이 마지막에 몰린다. 가능한 한 관찰 가능한 얇은 기능과 증거로 나눈다.

작업을 지나치게 잘게 나눈다

한 줄 변경마다 큐·작업 공간·리뷰 비용이 생기면 조정 비용이 구현보다 커진다. 같은 계약과 경계를 공유하고 함께 판정되는 변경은 묶는다.

병렬 수를 목표로 삼는다

대기 중인 에이전트가 보여도 의존 작업을 억지로 시작하지 않는다. 동시성은 독립 작업의 결과이지 공장의 성과 지표가 아니다.

계획 파일을 실행 중에 직접 덮어쓴다

어떤 그래프 버전에서 결과가 나왔는지 알 수 없다. 계획 변경은 버전과 승인 이벤트를 가진다.

운영 판단: 합칠까 나눌까

다음 질문에 ‘예’가 많으면 작업을 합친다.

  • 둘이 같은 제품 결정을 공유하는가?
  • 하나만 완료하면 저장소가 유효하지 않은 중간 상태인가?
  • 항상 같은 파일과 리뷰어를 요구하는가?
  • 독립 게이트를 만들기 어려운가?
  • 조정 비용이 예상 구현 시간과 비슷한가?

다음 질문에 ‘예’가 많으면 나눈다.

  • 서로 다른 모듈 경계와 테스트가 있는가?
  • 한 결과를 다른 작업이 명시적 계약으로 소비하는가?
  • 실패·되돌리기 범위를 줄일 수 있는가?
  • 서로 다른 위험 승인이나 전문 리뷰가 필요한가?
  • 실제 대기 시간을 줄일 만큼 작업이 긴가?

연습문제

  1. “검색 기능 구현”을 네 개 이하의 검증 가능한 수직 작업으로 나눠라.
  2. 순환 의존 A→B→C→A에서 공통 계약을 추출하는 방법과 작업을 합치는 방법을 비교하라.
  3. 파일 경로가 겹치지 않지만 의미 충돌이 가능한 작업 두 개의 예를 만들라.
  4. 계획 변경 뒤 실행 중인 하위 작업을 자동 통합하면 안 되는 이유를 입력 해시로 설명하라.

체크포인트

  • 주문 총액 기능이 증거를 만드는 작업 그래프로 표현됐다.
  • 모든 작업에 결과, 입력, 경계, 게이트, 위험, 예산이 있다.
  • 준비 상태와 대기 이유를 기계가 판정한다.
  • 병렬 실행 후보의 데이터·파일·의미 충돌을 검토했다.

다음 장에서는 각 작업에 필요한 문맥을 정확히 공급하고, 긴 실행에서 중요한 결정만 남기는 기억 구조를 만든다.