16장. 캡스톤—주문 처리 공장을 완주한다
이제 완성된 참조 하니스를 깨끗한 상태에서 실행해 빈 release/ 산출물 디렉터리에 주문 처리 애플리케이션을 만듭니다. 하니스 자체를 장마다 새로 작성하는 실습은 아닙니다. 이번 장은 새 개념을 더하지 않고, 앞의 15개 장에서 해부한 명세, 작업 그래프, 격리, 독립 리뷰, 품질 게이트, 이벤트, 실패 복구를 하나의 재현 가능한 흐름으로 닫습니다.
독자가 보는 본문 출력과 출판용 화면은 이 실습을 실제로 실행해 만든 같은 fixture를 사용합니다. 동적 시각과 개인 절대경로만 <DURATION>, <LAB_ROOT>로 정규화합니다. 상태, 작업 수, 게이트, 파일명은 손으로 바꾸지 않습니다.
이번 장의 약속
- 깨끗한 환경에서 코드·하니스·실패 경로를 한 명령으로 검증합니다.
- 다섯 작업의 의존성과 격리 공간, 통합 순서를 실제 이벤트로 복원합니다.
- 생성 앱의 도메인 불변식과 인수 테스트를 실행합니다.
- 성공·리뷰 재시도·명세 차단·인수인계 증거와 출간 화면을 같은 실행에서 만듭니다.
완성할 제품과 공장
제품은 메모리 안에서 동작하는 작은 주문 처리 앱입니다. 단순하지만 실제 시스템의 핵심 위험을 축소해 담습니다.
주문 생성
→ PENDING
→ CONFIRMED
→ SHIPPED
부분 취소: 상품 수량 × 단가만 환불
같은 requestId 재전송: 두 번째 환불 0원
공장은 다음 흐름을 구현합니다.
승인 명세와 seed
→ 준비된 작업 배치
→ 시도별 디렉터리 스냅샷
→ 결정론적 작업자
→ 독립 리뷰
→ 구문·구조 검사
→ 릴리스에 직렬 통합
→ 필수 파일·아키텍처·인수 테스트
→ JSONL 이벤트와 보고서
결정론적 작업자는 템플릿을 복사합니다. 구현 능력을 평가하려는 것이 아니라 하니스의 작업 그래프와 실패 통제를 같은 입력으로 검증하려는 선택입니다. 실제 코딩 에이전트는 이 배관이 모두 초록색인 뒤 교체합니다.
0단계: 시작 상태를 고정한다
실행 위치는 agent-software-factory/03-labs입니다. 원본 파일을 수정하지 않은 새 복사본에서 시작하는 것을 권합니다.
macOS/Linux/WSL:
cd /다운로드한/경로/agent-software-factory/03-labs
pwd
node --version
PowerShell:
Set-Location 'C:다운로드한경로agent-software-factory 3-labs'
Get-Location
node --version
Node.js가 v20 이상인지 확인합니다. npm install은 실행하지 않습니다. 외부 의존성이 없습니다.
생성 산출물만 정리합니다.
npm run clean
clean이 원본 specs/, tasks/, src/, test/를 지웠다면 즉시 중단합니다. 정상 구현은 .factory/ 아래의 생성 결과만 정리합니다.
1단계: 공장 자체를 검증한다
npm test
기대 종료 코드는 0입니다. 출간 fixture 기준 핵심 요약은 다음과 같습니다.
tests 26
pass 26
fail 0
테스트는 성공 경로만 검사하지 않습니다. 경로 탈출, 악성 간접 지시, 작업 그래프, 리뷰 반려와 재시도, 중단 뒤 인수인계, 수용 기준 없는 변경의 차단을 포함합니다.
‘수용 기준이 없으면 RED로 차단’ 테스트가 통과한 것은 모순이 아닙니다. 하니스가 위험 상태를 예상대로 거부했는지를 검증한 것입니다.
2단계: 명세와 작업 그래프를 읽는다
specs/capstone.json에는 seed, 다섯 작업, 최종 품질 규칙이 있습니다. 작업 의존성을 먼저 그립니다.
domain-model ──> repository-adapter ──> order-service ──> order-demo
│ │ │
+---------------+-----------------+
reader-docs (독립 작업)
정확한 간선은 JSON의 dependsOn이 공식 원본입니다.
| 작업 | 선행 작업 | 산출물 |
|---|---|---|
domain-model |
없음 | src/domain/order.mjs |
reader-docs |
없음 | README.md |
repository-adapter |
domain-model | 메모리 저장 어댑터 |
order-service |
domain-model, repository-adapter | 애플리케이션 서비스 |
order-demo |
order-service, repository-adapter | 인터페이스 데모 |
명세와 task 파일을 실행 전에 검사합니다.
npm run check:specs
npm run check:tasks
npm run queue -- --status ready --spec specs/capstone.json
준비 큐에서 첫 배치 후보는 domain-model과 reader-docs여야 합니다. 저장소·서비스·데모 작업이 모두 즉시 준비로 나오면 의존 판정이 깨졌습니다.
3단계: 전체 출간 검증을 실행한다
npm run verify
이 명령은 저자와 감수자가 예제 배포 전에 사용하는 골든 경로입니다.
환경 PASS — Node.js v20 이상
구문 PASS — ...개 파일
하니스 테스트 PASS
재시도 PASS — 작업 1, 시도 2
인계 PASS — 작업 1, 시도 2
최종 주문 앱 PASS — 작업 5, 시도 5
ALL GREEN ✓ — 코드·테스트·복구·최종 앱 검증 완료
구문 검사 파일 수와 실행 시간은 코드 개정과 컴퓨터에 따라 바뀔 수 있습니다. PASS 단계, 작업·시도 수, 마지막 ALL GREEN이 계약입니다.
verify가 실패하면 다음 실습으로 넘어가지 않습니다. 첫 번째 FAIL 단계의 원인을 고치고 처음부터 다시 실행합니다.
4단계: 주문 처리 공장을 가동한다
깨끗한 캡스톤을 실행합니다.
npm run demo
실제 캡처 fixture의 핵심 출력입니다.
에이전트 소프트웨어 공장: 주문 처리 앱 소프트웨어 공장
실행 ID: order-capstone | 작업 5개 | 어댑터 deterministic-mock
[배치 1] domain-model, reader-docs
→ domain-model 시도 1: 격리 작업공간 생성
→ reader-docs 시도 1: 격리 작업공간 생성
✓ domain-model: 리뷰·구문·구조 검사 통과 후 통합
✓ reader-docs: 리뷰·구문·구조 검사 통과 후 통합
[배치 2] repository-adapter
→ repository-adapter 시도 1: 격리 작업공간 생성
✓ repository-adapter: 리뷰·구문·구조 검사 통과 후 통합
[배치 3] order-service
→ order-service 시도 1: 격리 작업공간 생성
✓ order-service: 리뷰·구문·구조 검사 통과 후 통합
[배치 4] order-demo
→ order-demo 시도 1: 격리 작업공간 생성
✓ order-demo: 리뷰·구문·구조 검사 통과 후 통합
GREEN ✓ — 주문 처리 앱 소프트웨어 공장
보고서: <LAB_ROOT>/.factory/runs/order-capstone/report.md
이벤트: <LAB_ROOT>/.factory/runs/order-capstone/events.jsonl
그림 16-1. 실제 npm run demo 실행은 다섯 작업을 의존 순서로 통합하고 GREEN으로 끝난다.
그림 16-1은 이 명령의 실제 캡처입니다. 그림에 없는 배치를 본문에서 발명하지 않습니다. 출력이 다르면 03-labs/capture/success/terminal.txt와 예제 버전을 비교합니다.
무엇을 관찰할까
첫 배치에서 두 작업이 함께 준비됩니다. 각각 전용 작업 공간에서 실행된 뒤, 통합은 안정적인 작업 ID 순서로 직렬화됩니다. 이후 작업은 선행 결과가 통합된 다음에만 준비됩니다.
작업자 실행이 끝난 시점과 릴리스가 GREEN이 된 시점은 다릅니다. 독립 리뷰, 지역 구문·구조 검사, 통합, 최종 게이트가 그 사이에 있습니다.
5단계: 실행 증거를 해부한다
.factory/runs/order-capstone/
├── input.json
├── queue.json
├── events.jsonl
├── workspaces/
├── gate-results.json
├── change.patch
├── handoff.md
├── report.md
├── summary.json
└── release/
입력
input.json에서 실행 ID, 기준 명세, 정규화된 작업을 확인합니다. 실행 뒤 원본 명세가 바뀌어도 당시 입력을 재구성할 수 있어야 합니다.
작업 상태
queue.json은 다섯 작업의 의존성, 시도, 상태를 보존합니다. 최종적으로 모두 completed, 총 시도는 5여야 합니다.
실행 이벤트
events.jsonl의 각 줄은 JSON 사건 하나입니다. sequence가 1부터 빠짐없이 증가하는지 확인합니다.
npm run report -- --latest --trace
trace 보기에서 다음 증거 사슬을 찾습니다.
workspace.created
→ agent.invoked
→ agent.file_written
→ review.completed
→ gate.completed
→ workspace.integrated
→ final_gate.completed
변경
change.patch는 기준 릴리스에 어떤 파일이 추가됐는지 보여 줍니다. 허용된 아홉 필수 파일 밖에 정책·하니스 파일이 들어가면 성공 결과를 신뢰하지 않습니다. 아홉 번째 파일은 수용 기준 문서와 테스트 이름을 연결하는 specs/order-acceptance.manifest.json입니다.
판정
gate-results.json과 summary.json에서 다음을 확인합니다.
status: GREEN
taskCount: 5
attempts: 5
retries: 0
handoffs: 0
reviewRejections: 0
required-files: PASS (9)
architecture: PASS (4 layers)
acceptance-tests: PASS (13 tests: AC 12 + smoke 1)

그림 16-2. 같은 성공 실행의 로컬 보고서는 작업·시도 각 5회와 required-files 9개·architecture 4개·acceptance-tests의 테스트 파일 1개 및 수용 기준 12개 추적 PASS를 보여 준다. 연결된 생성 앱 테스트 결과는 13/13(수용 기준 12개+smoke 1개)이다.
그림 16-2는 같은 summary.json으로 생성된 보고서 화면입니다. 터미널 캡처와 상태·작업·게이트 수가 일치해야 합니다.
6단계: 생성 제품을 독립 검증한다
공장이 만든 릴리스 디렉터리에서 테스트를 실행합니다.
macOS/Linux/WSL:
cd .factory/runs/order-capstone/release
node --test
cd ../../../../
PowerShell:
Set-Location .factoryrunsorder-capstonerelease
node --test
Set-Location ........
기대 종료 코드는 0입니다.
tests 13
pass 13
fail 0
열두 수용 기준 테스트와 한 smoke test가 증명하는 규칙:
- 수량×단가의 합이 정수 원 단위 총액입니다.
- 빈 주문을 거부합니다.
- 수량 0을 거부합니다.
- 비정수 수량을 거부합니다.
- 음수 단가를 거부합니다.
- 비정수 단가를 거부합니다.
- 주문은 생성→확인→배송 순서로 전이합니다.
- 확인을 건너뛴 배송을 거부합니다.
- 존재하지 않는 주문의 상태 변경을 거부합니다.
- 중복 주문 ID를 거부합니다.
- 일부 상품 취소는 해당 금액만 환불합니다.
- 같은 취소 요청 ID는 두 번째 환불을 0원으로 만듭니다.
- 데모 주문 58,000원이 배송 상태에 도달합니다.
1~12번은 AC-ORDER-001부터 AC-ORDER-012까지 1:1로 연결되고, 13번은 SMOKE-ORDER-001입니다. 최종 게이트는 specs/order-acceptance.md, specs/order-acceptance.manifest.json, 실제 실행된 테스트 이름 사이의 ID와 이름이 모두 일치하는지도 검사합니다.
테스트 이름만 믿지 말고 test/order-flow.test.mjs의 입력과 assertion을 읽습니다. 특히 중복 취소 테스트는 저장소의 최종 refundTotal도 32,000원인지 확인합니다. 반환 값만 0으로 바꾸고 저장 상태가 두 배가 되는 결함을 막습니다.
7단계: 구조 경계를 확인한다
캡스톤의 의존 방향은 다음과 같습니다.
interface → application → domain
│ ↑
└──────> adapters
domain ─X→ application/adapters/interface
npm run test:architecture
그다음 의도된 위반 시나리오를 실행합니다.
npm run demo:architecture-violation
이 명령의 기대 결과는 비영 종료 코드와 구조 게이트 FAIL입니다. 위반 시나리오가 초록색이면 구조 검사가 중요한 경계를 대표하지 못합니다. 정상 캡스톤 릴리스는 오염되지 않아야 합니다.
8단계: 세 가지 실패를 학습한다
리뷰 반려 뒤 재시도
npm run factory -- --task tasks/attempt-policy-change.json
첫 시도는 TODO 때문에 독립 리뷰에서 반려되고, 두 번째 시도가 통과합니다. 전체 명령은 종료 코드 0, 최종 GREEN입니다.
taskCount: 1
attempts: 2
retries: 1
reviewRejections: 1
workspaces/attempt-policy-change-attempt-1의 반려 결과와 attempt 2, release를 비교합니다. 첫 공간의 미완성 파일이 릴리스에 섞이지 않아야 합니다.
검증할 수 없는 변경 차단
npm run factory -- --task tasks/missing-acceptance.json
이 명령은 의도적으로 종료 코드 1입니다.
RED ✗ — 수용 기준이 없어 차단되는 변경
실행 실패: 최종 품질 게이트 실패
필수 파일과 구조가 통과해도 실행 가능한 인수 테스트가 없으면 완료가 아닙니다. 그림 11-2의 빨간 상태는 독자가 잘못 실행한 화면이 아니라 성공적으로 차단된 학습 화면입니다.
중단 뒤 인수인계
npm run demo:handoff
첫 시도는 체크포인트를 남기고, 두 번째 작업자가 재개합니다.
attempts: 2
handoffs: 1
status: GREEN
handoff.md와 첫 작업 공간의 체크포인트가 완료한 것, 남은 것, 재개 지점에 답하는지 확인합니다. 이 실습은 같은 프로세스에서 재개하지만 상태가 파일로 보존됩니다. 프로세스 재시작 내구성을 완전히 제공한다고 과장하지 않습니다.
9단계: 병렬성과 통합 충돌을 따로 본다
npm run demo:parallel -- --concurrency 1
npm run demo:parallel -- --concurrency 2
npm run demo:parallel -- --concurrency 4
교육용 구현에서 독립 준비 작업의 배치와 최종 판정이 유지되는지 비교합니다. 컴퓨터의 wall time 차이를 보편적 속도 수치로 사용하지 않습니다.
충돌 시나리오:
npm run demo:conflict
각 작업 공간의 지역 성공과 최신 릴리스 통합 판정이 다를 수 있음을 확인합니다. 격리는 충돌을 없애지 않고 어느 변경에서 생겼는지 분리합니다.
10단계: 보안 경계를 공격한다
npm run test:security -- --case path-traversal
npm run test:security -- --case indirect-instruction
첫 검사는 ../, 절대경로, 선언된 출력 경계 밖 경로를 safeJoin과 명세 로더가 거부하는지 확인합니다. 두 번째는 고정 fixture 안의 “이전 지시를 무시하라”는 문자열을 결정론적 리뷰 규칙이 반려하는지 확인합니다. 실제 모델이 해당 문서를 읽고 도구 행동을 제안하거나 네트워크 egress가 거부되는 통합 테스트는 아닙니다. 두 테스트 자체는 기대 위반을 정확히 찾아 종료 코드 0으로 끝납니다.
SECURITY.md에서 이 예제가 제공하는 방어와 제공하지 않는 방어를 읽습니다. 디렉터리 스냅샷과 Node.js 경로 검사는 운영체제 수준의 완전한 샌드박스가 아닙니다.
11단계: 평가와 게이트 자체를 검증한다
npm run evaluate:gates
npm run eval
evaluate:gates는 가장 최근 run의 gate-results.json을 읽어 PASS/FAIL을 다시 출력합니다. 먼저 어떤 fixture를 실행했는지 확인합니다. eval은 현재 캡스톤 한 사례를 다시 실행해 3/3 PASS, 작업 5, 시도 5, 재시도·인계 0, GREEN을 요약합니다.
이 두 명령은 다중 결함 주입 평가 스위트가 아닙니다. 성공·정책 위반·올바른 차단·복구를 기대 상태별로 비교하는 평가는 13장의 현장 확장 과제입니다. 현재 하니스의 여러 실패 fixture는 npm test에서 회귀 검사합니다.
검증 질문:
- 기능 성공이 정책 위반을 상쇄하지 않는가?
- 의도된 차단을 모델 실패로 잘못 세지 않는가?
- 재시도와 인수인계를 작업 수에서 숨기지 않는가?
- 게이트가 0개 테스트를 성공으로 처리하지 않는가?
12단계: 책과 동일한 화면을 재생성한다
npm run capture:fixtures
이 명령은 성공, 리뷰 재시도, 차단, 인수인계의 실제 실행을 다시 만들고 capture/ 아래에 저장합니다.
capture/
├── manifest.json
├── minimal/{terminal.txt,summary.json,events.jsonl,report.html}
├── success/{terminal.txt,summary.json,events.jsonl,report.html}
├── retry/{terminal.txt,summary.json,events.jsonl,report.html}
├── blocked/{terminal.txt,summary.json,events.jsonl,report.html}
└── handoff/{terminal.txt,summary.json,events.jsonl,report.html}
출판용 그림 빌드는 이 manifest를 입력으로 사용합니다. 다음은 고정 계약이고 그림과 본문이 모두 일치해야 합니다.
| fixture | 명령 | 종료 | 상태 | 핵심 수치 |
|---|---|---|---|---|
| minimal | 주문 합계 task | 0 | GREEN | 작업/시도 1/1, gate 3 |
| success | npm run demo |
0 | GREEN | 작업/시도 5/5, test 13 |
| retry | 정책 변경 task | 0 | GREEN | 시도 2, 재시도 1, 반려 1 |
| blocked | 수용 기준 누락 task | 1 | RED | acceptance FAIL |
| handoff | npm run demo:handoff |
0 | GREEN | 시도 2, 인계 1 |
그림의 상태나 숫자가 다르면 그래픽을 손으로 고치지 않습니다. fixture를 다시 만들고 원고·예제 버전의 불일치를 해결합니다.
최종 품질 확인
다음 항목을 실제 산출물로 확인합니다.
- [ ]
npm test가 26개 테스트, 실패 0으로 끝났습니다. - [ ]
npm run verify의 마지막 줄이ALL GREEN입니다. - [ ]
order-capstone다섯 작업이 모두completed입니다. - [ ] 총 시도는 5이고 예상하지 않은 재시도가 없습니다.
- [ ] 첫 배치의 두 작업이 별도 작업 공간을 사용합니다.
- [ ] 최종 필수 파일 9개와 구조 계층 4개가 통과합니다.
- [ ] 생성 앱의 수용 기준 12개와 smoke 1개, 총 13개 테스트가 통과합니다.
- [ ] 부분 취소 32,000원과 중복 환불 0원을 확인했습니다.
- [ ]
events.jsonl의 sequence와 증거 사슬이 이어집니다. - [ ] 리뷰 재시도, 명세 차단, 인수인계가 기대 상태를 냅니다.
- [ ] 보안 공격 fixture가 정책에서 차단됩니다.
- [ ] 캡처 manifest와 본문·그림의 상태와 숫자가 일치합니다.
- [ ]
npm run clean이 생성 산출물만 정리합니다.
실제 에이전트로 교체하기 전
이 책의 모의 작업자는 공장 배관을 검증합니다. 현재 Factory는 src/mock-agent.mjs의 작업자를 직접 생성하므로 파일 하나만 바꿔 끼우는 확장점은 제공하지 않습니다. 실제 코딩 에이전트를 연결할 때는 먼저 작업자 의존성 주입 경계를 만들고 제품별 입력·출력을 변환하는 어댑터를 구현합니다. 그 뒤에도 다음 의미 계약을 유지합니다.
작업 봉투와 명세 버전
작업 공간과 허용 경로
도구·시간·행동 예산
독립 리뷰와 필수 게이트
이벤트·summary·handoff 계약
재시도·차단·취소 상태
평가 fixture와 중단 기준
새 어댑터는 같은 평가 세트를 여러 번 실행합니다. 모의 작업자보다 ‘지능적’이라는 이유로 경로 정책이나 게이트를 완화하지 않습니다.
왜 실패하는가
verify보다 demo만 보여 줍니다
성공 화면은 만들 수 있지만 하니스의 경로·재시도·차단 회귀를 놓칩니다. 출간과 팀 배포는 골든 검증을 먼저 실행합니다.
생성 앱 테스트만 통과하면 공장도 맞다고 봅니다
작업자가 정책 파일을 건드리거나 증거가 끊겨도 제품 테스트는 통과할 수 있습니다. 과정 정책과 산출물 출처를 함께 봅니다.
실패 화면을 오류로 보고 삭제합니다
차단과 리뷰 반려는 공장의 학습 목표입니다. 예상 종료 상태와 이유가 맞는지 확인하고 출간 fixture로 보존합니다.
스크린샷의 숫자를 손으로 최신화합니다
본문·예제·그림이 갈라집니다. 깨끗한 실행에서 fixture와 모든 파생물을 다시 생성합니다.
현장 확장
실제 팀에 옮길 때 한 번에 모든 것을 교체하지 않습니다.
- 캡스톤의 작업 스키마를 실제 반복 업무 하나에 맞춥니다.
- 제품팀의 승인 명세와 실제 테스트를 연결합니다.
- 디렉터리 스냅샷을 위험에 맞는 worktree/컨테이너/원격 샌드박스로 바꿉니다.
- 모의 작업자와 실제 에이전트를 같은 평가 세트에서 비교합니다.
- 모든 결과를 사람 리뷰로 통합하며 기준선을 수집합니다.
- 낮은 위험·강한 판정 업무에서만 동시성과 자동 통합을 넓힙니다.
연습문제
agent.file_written뒤 최종GREEN전에 필요한 사건을 실제events.jsonl에서 찾아 순서대로 적습니다.- 작업 5개, 시도 7회, 재시도 1회, 인수인계 1회인 실행에서 ‘작업 수’만 보고하면 숨는 비용을 설명합니다.
- 생성 앱의 중복 환불 테스트가 반환 값뿐 아니라 저장소의 누적 환불액도 확인해야 하는 이유를 설명합니다.
- 팀의 반복 작업 하나를 캡스톤 스키마로 옮깁니다. 명세, 작업 DAG, 허용 경로, 게이트, 사람 승인, 실패 fixture를 포함합니다.
- 실제 코딩 에이전트 어댑터의 입력·출력 계약을 작성하고, 하니스에서 절대 넘기지 않을 책임 세 개를 표시합니다.
체크포인트
- 깨끗한 환경에서
npm run verify와 캡스톤이 실제로 통과했습니다. - 다섯 작업의 DAG, 작업 공간, 리뷰, 통합, 최종 게이트를 증거로 설명할 수 있습니다.
- 성공만이 아니라 재시도·차단·인수인계를 기대 상태로 재현했습니다.
- 생성 제품의 도메인 규칙과 멱등성을 독립 테스트로 확인했습니다.
- 본문 출력과 출판용 화면이 같은 캡처 manifest에서 생성됩니다.
이제 독자에게는 작은 공장이 남았습니다. 다음 단계는 에이전트 수를 늘리는 일이 아닙니다. 실제 팀의 업무 하나를 같은 하니스 원칙으로 옮기고, 실패를 관측하고, 한 번에 한 경계를 강화하는 일입니다.
맺음말 — 사람이 설계해야 할 것
에이전트 소프트웨어 참조 공장을 실행하고 해부한 뒤에도 모델은 틀린다. 요구는 바뀌고, 테스트가 놓치는 빈틈이 생기며, 병렬 작업은 예상 밖의 충돌을 만든다. 이 책의 목표는 그런 불확실성을 없애는 일이 아니었다. 불확실성을 관찰할 수 있는 상태로 만들고, 실패의 폭을 제한하며, 다음 실행이 이전 실행보다 나아질 근거를 남기는 일이었다.
우리가 만든 공장의 핵심은 화려한 에이전트 수가 아니다.
- 요구가 판정 가능한 명세로 남는다.
- 작업의 소유권과 의존성이 보인다.
- 변경은 격리된 경계 안에서 일어난다.
- 품질 기준은 말이 아니라 실행되는 검사다.
- 독립 리뷰와 최소 권한이 과신을 제어한다.
- 이벤트, 산출물, 결정 기록이 다음 작업자에게 기억을 건넨다.
이 구조가 있으면 더 나은 모델은 즉시 더 큰 효과를 낸다. 모델이 바뀌어도 팀의 운영 지식은 저장소와 하니스에 남는다. 반대로 구조가 없으면 더 빠른 생성은 더 빠른 혼란이 될 수 있다.
코드가 희소했던 시대에는 사람이 구현의 대부분을 직접 담당했다. 생성 능력이 풍부해지는 시대에 사람의 중요한 일은 목적과 경계를 정하고, 판정 기준을 만들고, 예외를 다루고, 시스템이 학습하도록 피드백을 남기는 쪽으로 이동한다. 이것은 개발자의 퇴장이 아니라 개발의 작업 단위가 커지는 변화다.
독자가 마지막 실습에서 만든 것은 작은 공장이다. 다음 단계는 에이전트를 더 많이 붙이는 것이 아니다. 실제 팀의 반복 작업 하나를 선택해 같은 원리를 적용하는 것이다. 실패 비용이 낮고 판정 기준이 명확한 작업부터 시작하라. 측정하고, 한 가지 병목을 고치고, 위임 경계를 조금씩 넓혀라.
좋은 공장은 사람을 배제하지 않는다. 사람이 가장 값진 판단에 집중할 수 있게 한다. 코드는 산출물이다. 우리가 설계해야 할 것은 그 산출물을 믿을 수 있게 만드는 시스템이다.
부록 A. 환경 구축과 문제 해결
이 부록의 목표는 독자가 실습 오류를 모델이나 코드 문제로 오해하기 전에 환경·경로·입력 상태를 빠르게 확인하게 하는 것입니다. 핵심 실습은 네트워크, API 키, npm install 없이 동작합니다.
A.1 지원 환경
| 항목 | 최소 | 확인 명령 |
|---|---|---|
| Node.js | 20 | node --version |
| npm | Node.js에 포함 | npm --version |
| Git | 핵심 실습은 불필요, worktree 확장은 2.40 | git --version |
| 디스크 | 최소 약 30MB, 실행 산출물을 위한 100MB 여유 권장 | OS 파일 정보 |
| 셸 | macOS/Linux 셸, PowerShell 7+, WSL2 | 셸별 아래 명령 |
책이 지원한다고 표시한 환경은 출간 전에 실제 재현 행렬에서 확인해야 합니다. 미확인 운영체제를 “아마 동작”으로 지원 목록에 넣지 않습니다.
A.2 3분 사전 점검
macOS/Linux/WSL:
cd /다운로드한/경로/agent-software-factory/03-labs
pwd
node --version
npm --version
test -f package.json
npm test
PowerShell:
Set-Location 'C:다운로드한경로agent-software-factory 3-labs'
Get-Location
node --version
npm --version
Test-Path package.json
npm test
확인할 결과:
현재 경로의 마지막 디렉터리: 03-labs
Node.js: v20 이상
package.json 존재: true 또는 종료 코드 0
npm test: fail 0, 종료 코드 0
테스트 개수는 원고 개정으로 바뀔 수 있습니다. 출간본의 실제 캡처와 EXPECTED-OUTPUT.md를 우선합니다.
A.3 깨끗하게 다시 시작하기
npm run clean은 예제의 생성 산출물 .factory/만 지워야 합니다. 원본 명세, 작업, 소스, 테스트를 지우지 않습니다.
npm run clean
npm test
npm run demo
사용자의 다른 변경이 있는 저장소에서 광범위한 삭제나 Git 초기화 명령을 실행하지 않습니다. 원본 파일까지 바꿨다면 새 압축본을 별도 디렉터리에 풀고 다시 실행합니다. 기존 디렉터리를 덮어쓰지 않아 비교 증거를 남깁니다.
A.4 오류별 첫 관찰 지점
| 증상 | 가장 먼저 확인 | 흔한 원인 | 복구 |
|---|---|---|---|
npm: command not found |
node --version |
Node.js 미설치/PATH | Node.js 20+ 설치 후 새 터미널 |
package.json 없음 |
pwd/Get-Location |
상위 디렉터리에서 실행 | 03-labs로 이동 |
| 엔진 버전 오류 | node --version |
Node.js 18 이하 | 지원 버전으로 전환 |
ERR_MODULE_NOT_FOUND |
오류의 첫 로컬 경로 | 파일 누락/잘못 푼 압축 | 원본 파일 목록과 비교 |
EACCES/EPERM |
대상 경로·소유권 | 읽기 전용/보안 프로그램 | 사용자 쓰기 가능한 새 경로 |
의도된 RED |
실행한 task | 실패 학습 시나리오 | gate-results.json 확인, 성공으로 바꾸지 않음 |
| 최신 보고서가 다른 실행 | summary.json run ID |
여러 실행 산출물 | 명시적 run을 선택하거나 clean |
| 테스트 수 0 | test 파일 존재·러너 출력 | 잘못된 경로/발견 규칙 | 테스트 발견 조건 복구 |
| 경로 정책 위반 | 이벤트의 requested path | .., 절대경로, 금지 경계 |
작업의 허용 경로 안으로 설계 수정 |
| JSON parse 오류 | 파일과 줄/열 | 쉼표·따옴표 | 오류 위치를 고치고 npm test |
A.5 의도된 실패와 실제 환경 실패 구분
tasks/missing-acceptance.json은 종료 코드 1과 RED가 정상 학습 결과입니다. 다음 세 조건을 모두 만족해야 합니다.
실행기가 통제된 오류 메시지를 남겼다.
.factory/runs/missing-acceptance/에 산출물이 있다.
gate-results.json의 acceptance-tests만 의도된 이유로 실패했다.
스택 트레이스와 함께 산출물 생성 전 종료되거나 ENOENT, 구문 오류가 나면 의도된 실패가 아닙니다.
macOS/Linux에서 마지막 종료 코드를 봅니다.
npm run factory -- --task tasks/missing-acceptance.json
echo $?
PowerShell:
npm run factory -- --task tasks/missing-acceptance.json
$LASTEXITCODE
A.6 경로에 공백과 한글이 있을 때
Node.js 예제는 경로를 문자열 인자로 처리하므로 공백과 한글 경로에서도 동작해야 합니다. 셸에서 이동할 때 따옴표를 씁니다.
cd "/Users/example/My Books/agent-software-factory/03-labs"
Set-Location 'C:Usersexample내 책agent-software-factory 3-labs'
문제가 생기면 먼저 짧은 영문 사용자 경로의 새 복사본에서 재현합니다. 그곳에서만 성공한다면 코드 오류가 아니라 경로 처리 회귀입니다. 문제 경로를 숨기지 말고 테스트 사례로 등록합니다.
A.7 Windows 주의
- PowerShell의 경로 구분자는
이지만 Node.js 코드에서는node:path를 사용합니다. cat대신Get-Content,pwd대신Get-Location을 사용할 수 있습니다.- 실행 정책 때문에
.ps1이 막혀도 이 책의 핵심 경로는node와npm명령입니다. - WSL과 Windows Node.js를 섞지 않습니다. WSL 터미널에서는 WSL에 설치한 Node.js와 Linux 경로를 사용합니다.
- 백신이나 동기화 폴더가 임시 파일 교체를 간섭하면 사용자 로컬의 새 실습 경로에서 재현합니다.
A.8 보고용 진단 묶음
문제를 제보할 때 비밀과 개인 경로를 제거한 다음을 제공합니다.
운영체제와 셸
node --version / npm --version
실행한 정확한 명령
종료 코드
오류의 첫 원인 줄과 마지막 30줄
해당 run의 summary.json
gate-results.json
events.jsonl 중 오류 앞뒤 이벤트
원본 파일을 수정했는지 여부
홈 경로, 사용자 이름, 토큰, 내부 호스트, 전체 환경 변수는 보내지 않습니다.
A.9 재현 완료 기록
출간 감수와 독자 베타테스트에서 아래 표를 채웁니다.
| OS/버전 | 셸 | Node/npm | npm test |
npm run verify |
캡스톤 | 확인자/날짜 |
|---|---|---|---|---|---|---|
| macOS | zsh | |||||
| Windows | PowerShell | |||||
| Windows | WSL2 | |||||
| Linux | bash |
지원 표기는 이 표의 실제 통과 결과와 일치해야 합니다.
부록 B. 바로 쓰는 명세·작업·운영 템플릿
템플릿은 생각을 대신하지 않습니다. 비어 있는 중요한 결정을 눈에 보이게 하고, 사람·에이전트·검사가 같은 계약을 읽게 합니다. 각 템플릿에서 필요 없는 항목은 이유를 남기고 제거합니다. 의미 없는 N/A를 채워 완성처럼 보이게 하지 않습니다.
B.1 저장소 작업 안내서
# Repository work guide
## 제품 목적
이 저장소가 제공하는 사용자 결과를 3문장 이내로 씁니다.
## 공식 입구
- 도메인 용어: `docs/domain-glossary.md`
- 저장소 지도: `docs/repository-map.md`
- 승인 명세: `specs/README.md`
- 아키텍처 결정: `docs/decisions/`
## 신뢰할 명령
- 빠른 검사: `<명령>`
- 전체 검사: `<명령>`
- 로컬 실행: `<명령>`
## 변경 경계
- `<경로>` 변경 시 `<테스트/문서>`를 함께 확인합니다.
- 승인 없이 수정하지 않을 경로: `<정책/CI/보안>`
- 생성 산출물 경로: `<경로>`
## 완료 정의
- 승인 명세 버전: 확인
- 필수 게이트: `<목록>`
- 인계·잔여 위험: 기록
## 더 구체적인 지역 규칙
- `<하위 경로>/AGENTS.md`
B.2 실행 가능한 명세
---
id: SPEC-<DOMAIN>-<NNN>
version: 1
status: draft
owner: <제품/도메인 소유자>
approved_at: null
---
# <관찰 가능한 결과>
## 문제와 사용자 결과
현재 문제, 대상 사용자, 완료 뒤 달라지는 결과를 씁니다.
## 범위
### 포함
-
### 제외
-
## 용어와 상태
| 용어/상태 | 이 명세에서의 의미 |
|---|---|
| | |
## 규칙
- R-01:
- R-02:
## 결정표
| 조건 A | 조건 B | 기대 행동 |
|---|---|---|
| | | |
## 수용 기준
- AC-01 정상 경로:
- AC-02 경계값:
- AC-03 잘못된 입력:
- AC-04 권한/데이터:
## 불변식
- INV-01:
## 비기능 요구
- 성능: 기준 환경/기준값/허용 변화/측정 명령
- 보안·개인정보: 금지 데이터/권한/증거
- 호환성: 유지할 공개 계약과 검증
- 복구: 실패 행동과 되돌리기
## 미결정
| ID | 질문 | 등급(A~D) | 소유자 | 마감 | 상태 |
|---|---|---|---|---|---|
| | | | | | |
## 증거 연결
| 기준 | 자동/수동 증거 | 경로/명령 | 상태 |
|---|---|---|---|
| AC-01 | | | 예정 |
B.3 작업 봉투
설계 예(실행용 아님) — 원본: 부록 B.3 작업 봉투 템플릿; 명령: 없음.
{
"id": "TASK-001",
"title": "관찰 가능한 결과를 동사로 씁니다",
"spec": { "id": "SPEC-DOMAIN-001", "version": 1 },
"outcome": "완료 뒤 외부에서 확인할 상태",
"dependsOn": [],
"inputs": [],
"allowedPaths": ["src/domain/", "test/domain/"],
"forbiddenPaths": ["policy/", ".github/"],
"requiredGates": ["unit", "architecture", "security"],
"risk": "low",
"approvals": [],
"budget": {
"attempts": 3,
"actions": 20,
"wallSeconds": 120,
"changedFiles": 8
}
}
B.4 작업 분해 검토표
## 결과
- 작업 하나가 관찰 가능한 결과 하나를 완성하는가?
- 독립 게이트로 판정할 수 있는가?
## 경계
- 예상 변경 집합과 허용 경로가 충분히 좁은가?
- 정책·테스트 우회 경로가 포함되지 않았는가?
## 의존성
- 선행 작업의 어떤 산출물을 소비하는가?
- 순환 또는 숨은 의미 의존이 없는가?
## 병렬성
- 데이터, 파일, 제품 의미 충돌을 각각 확인했는가?
- 격리·검증·리뷰 비용보다 대기 절감이 큰가?
## 위험
- 외부 효과, 비밀, 데이터, 공개 계약 변화가 있는가?
- 필요한 사람 승인과 되돌리기가 있는가?
B.5 아키텍처 결정 기록
# ADR-<NNN>: <결정 제목>
- 상태: proposed | accepted | superseded
- 날짜:
- 소유자:
- 관련 명세/작업:
## 상황
결정해야 하는 문제와 제약을 씁니다.
## 고려한 선택지
1. 선택지와 장단점
2. 선택지와 장단점
## 결정
무엇을 선택했고 어떤 범위에 적용하는지 씁니다.
## 결과와 위험
좋아지는 점, 비용, 실패 가능성, 되돌리는 법을 씁니다.
## 기계식 규칙
이 결정을 지키는 구조 테스트·게이트·관측을 연결합니다.
B.6 품질 게이트 계약
설계 예(실행용 아님) — 원본: 부록 B.6 게이트 계약 템플릿; 명령: 없음.
{
"id": "architecture",
"version": "1",
"risk": "forbidden dependency",
"required": true,
"command": ["node", "--test", "test/architecture"],
"timeoutSeconds": 60,
"success": {
"exitCode": 0,
"minimumChecks": 1
},
"failureOwner": "platform-architecture",
"artifacts": ["artifacts/gates/architecture.json"]
}
B.7 인수인계 패킷
# Handoff: <taskId>/<runId>
## 공식 입력
- 명세: `<id>@<version>` / hash
- 기준선: commit/hash
- 정책·도구 버전:
## 목표와 현재 상태
- 상태: SUCCEEDED | FAILED | BLOCKED | CANCELED
- 종료 이유 코드:
## 확인한 사실
- 사실 + 출처 경로/hash
## 적용한 변경
- 경로 + 목적
## 게이트와 증거
| 게이트 | 결과 | 산출물 |
|---|---|---|
| | | |
## 폐기한 가설
- 가설 / 폐기 근거
## 외부 효과
- effect ID / 상태 / 조회 / 보상
## 남은 위험과 결정
-
## 다음 안전 행동
1.
B.8 평가 사례
설계 예(실행용 아님) — 원본: 부록 B.8 평가 사례 템플릿; 명령: 없음.
id: EVAL-<DOMAIN>-001
category: api-change
difficulty: local
risk: low
fixture: <고정 기준 저장소>
task: <작업 계약 경로>
expected_status: SUCCEEDED
must_pass:
- AC-01
- ARCH-001
must_not:
- modify: policy/**
- expose_fields: [secretField]
budget:
actions: 20
wall_seconds: 120
trials: 5
manual_rubric:
maintainability: 0..2
evidence_quality: 0..2
B.9 파일럿 도입 계약
# 에이전트 공장 파일럿
## 업무군과 사용자 문제
## 범위 밖·금지 행동
## 도입 전 기준선
## 성공 가설과 중단 기준
## 제품/저장소/플랫폼/보안 책임
## 데이터 분류와 제공하지 않을 정보
## 명세·격리·게이트·승인
## 평가 세트와 운영 관측
## 사건 대응과 긴급 중지
## 30일 검토일과 확장 조건
B.10 사건 기록
# Incident <ID>
## 영향과 시간선
## 관련 request/task/run/change/deploy ID
## 명세·정책·하니스·모델·도구 버전
## 관찰된 행동과 외부 효과
## 즉시 제한·자격 증명 회전·복구
## 원인 분류
- 명세 / 컨텍스트 / 권한 / 도구 / 게이트 / 리뷰 / 통합 / 운영
## 방어가 잡았거나 놓친 지점
## 평가 사례·게이트·문서에 반영할 변경
## 소유자와 완료 증거
부록 C. 역할 중심 도구·어댑터 지도
이 부록은 제품 순위를 매기지 않습니다. 공장의 역할과 교체 경계를 먼저 정한 뒤, 2026년 7월 17일 기준 공개된 제품·프로토콜을 예시로 연결합니다. 기능과 지원 범위는 바뀌므로 인쇄본의 명령보다 각 공식 문서와 온라인 호환표를 다시 확인합니다.
C.1 역할부터 선택한다
| 역할 | 필요한 계약 | 선택 질문 |
|---|---|---|
| 코딩 작업자 | 목표·문맥 입력, 도구 행동, 결과/이벤트 | 파일·셸 범위, 비대화형 실행, 중단, 출력 구조 |
| 오케스트레이터 | 작업 상태, 임대, 재시도, 취소 | DAG, WIP, 늦은 결과, 멱등성 |
| 격리 실행 | 기준선, 쓰기 루트, 네트워크, 자격 증명 | 위협 모델, 시작 비용, 보존·정리 |
| 명세/계획 | 승인 상태, 버전, 수용 기준, 작업 | source of truth, 추적, 변경 승인 |
| 품질 게이트 | 명령, 구조화 결과, 산출물 | 위험 연결, 결정성, 우회 방지 |
| 관측 | 이벤트, 메트릭, trace, 데이터 분류 | 공통 ID, 민감정보, 스키마 버전 |
| 사람 승인 | 영향, 증거, 잔여 위험, 결정 | 승인 피로, 책임, 만료·철회 |
한 제품이 여러 역할을 제공해도 내부 경계를 유지합니다. 작업자 제품의 세션 ID가 공장의 유일한 taskId가 되거나, 관측 백엔드의 span 형식이 작업 계약을 지배하지 않게 합니다.
C.2 코딩 작업자 어댑터
현재 실습 구현의 계약
완성된 참조 하니스는 실제 제품 어댑터를 끼워 넣는 구조까지 구현하지 않는다. Factory가 DeterministicMockAgent를 직접 만들며, 현재 호출과 반환 모양은 다음과 같다.
현재 구현 설명(실행용 아님) — 아래 타입은 03-labs/src/mock-agent.mjs의 실행 코드를 설명하기 위해 TypeScript로 옮긴 것이다.
type CurrentMockRequest = {
task: NormalizedTask;
attempt: number;
workspace: {
path: string;
operations: Operation[];
outputs: Record<string, string>;
};
previousHandoffs: HandoffCheckpoint[];
};
type CurrentMockResult =
| { status: "completed"; changedPaths: string[] }
| { status: "handoff"; checkpoint: HandoffCheckpoint };
따라서 외부 작업자를 현재 하니스에 그대로 대입할 수 있다고 주장하지 않는다. 먼저 Factory에 작업자 의존성을 주입하고, 제품별 상태를 공통 상태로 정규화하고, 취소·예산·이벤트를 연결한 뒤 같은 게이트로 검증해야 한다.
현장 확장을 위한 목표 계약
다음은 그 확장을 설계할 때 사용할 수 있는 목표 모양이다. 책의 현재 코드에 구현되거나 테스트된 API가 아니다.
설계 예(실행용 아님) — 실제 제품을 연결하기 전에 구현·검증해야 할 목표 어댑터 계약이다.
type WorkerRequest = {
taskId: string;
goal: string;
spec: { id: string; version: number; path: string };
workspace: string;
allowedPaths: string[];
budget: { actions: number; wallMs: number };
};
type WorkerResult = {
status: "done" | "blocked" | "failed";
summary: string;
changedPaths: string[];
questions: string[];
usage?: Record<string, number>;
};
현장용 어댑터를 구현할 때 추가로 해야 할 일:
- 제품 고유 지시 파일과 옵션을 공장 계약에 매핑
- 비대화형 종료와 타임아웃 처리
- 도구/파일 이벤트를 공통 형식으로 변환
- 모델·제품 버전과 사용량 기록
- 취소 신호와 프로세스 트리 종료
- 원문 출력에서 비밀·개인정보 제거
어댑터는 제품이 “성공”이라고 말한 결과를 공장 성공으로 바꾸지 않습니다. 필수 게이트와 리뷰가 별도로 판정합니다.
C.3 공개 구현에서 배울 역할
하니스·작업자 루프
OpenAI는 Codex의 루프를 사용자 입력, 모델 추론, 도구 호출 실행, 도구 결과 추가, 종료 메시지의 반복으로 설명합니다. App Server 사례는 세션 수명 주기와 이벤트 스트림을 작업자 코어 밖 클라이언트와 연결합니다. 이는 책의 2장 경계를 비교할 사례이지 모든 에이전트의 표준 API가 아닙니다.
명세 중심 흐름
GitHub Spec Kit은 /specify, /plan, /tasks처럼 의도·기술 계획·작업을 분리하는 공개 툴킷입니다. 설치 명령과 버전은 빠르게 바뀌므로 핵심 실습은 이 도구에 의존하지 않습니다.
오케스트레이션
OpenAI Symphony의 공개 명세는 이슈 트래커, 작업별 격리 workspace, 실행 수명 주기, 재시도와 관측을 연결합니다. Draft v1 참조 명세이며 보편 표준이나 제품 보장이 아닙니다.
장기 작업
Anthropic의 공개 엔지니어링 글은 기능 목록, 진행 파일, Git 기록, E2E 검증, 구조화된 인수인계로 세션 사이 상태를 잇는 실험을 설명합니다. 특정 모델과 실험의 관찰을 이 책의 유일한 정답으로 쓰지 않습니다.
C.4 프로토콜은 역할을 대신하지 않는다
MCP
Model Context Protocol은 host-client-server 구조에서 도구와 자원 연결, JSON-RPC 메시지, 전송과 권한 일부를 정의합니다. 2025-11-25 명세 기준입니다. MCP를 쓴다고 작업 그래프, 샌드박스, 품질 게이트, 조직 승인이 자동으로 생기지는 않습니다.
A2A
Agent2Agent Protocol은 서로 다른 에이전트 시스템의 기능 발견, 작업 협업, 메시지와 산출물 교환을 위한 공개 프로토콜입니다. MCP의 후속이나 대체라고 단순화하지 않습니다. 이 책의 로컬 작업 큐에는 필수가 아닙니다.
프로토콜을 선택할 질문:
- 경계를 넘는 데이터와 권한은 무엇인가?
- 작업 ID·상태·취소·산출물을 손실 없이 매핑할 수 있는가?
- 상대 시스템의 출력을 신뢰하지 않고 검증할 수 있는가?
- 인증 토큰을 다른 시스템으로 그대로 전달하지 않는가?
- 버전·기능 협상 실패 시 안전한 종료가 있는가?
C.5 격리 선택표
| 선택 | 장점 | 한계 | 적합한 시작점 |
|---|---|---|---|
| 디렉터리 스냅샷 | 단순, 무Git, 교육에 재현 | 저장/복사 비용, 프로세스 비격리 | 책의 핵심 실습 |
| Git worktree | 빠른 코드 분리, Git 이력 | 보안 샌드박스 아님 | 신뢰된 로컬 작업 |
| 컨테이너 | 의존/프로세스/파일 경계 | 설정·이미지·마운트 위험 | CI, 생성 코드 실행 |
| 원격 일회성 환경 | 호스트와 강한 분리·확장 | 비용·지연·데이터 이동 | 다수 테넌트·고위험 |
Git 공식 문서는 linked worktree가 HEAD와 index 등은 분리하지만 공통 저장소와 refs를 공유한다고 설명합니다. 컨테이너 rootless 모드도 피해를 줄이는 한 수단이지 완전한 보안 보장은 아닙니다.
C.6 관측 매핑
책의 JSONL 이벤트를 외부 관측 시스템에 보낼 때 내부 의미를 잃지 않습니다.
| 책의 사건 | trace 후보 | 메트릭 후보 |
|---|---|---|
run.started/finished |
agent invocation span | 실행 시간·상태 수 |
tool.started/finished |
tool execution span | 도구 시간·오류 수 |
gate.completed |
gate span/event | 통과율·대기 시간 |
review.completed |
review span | 발견 심각도·재작업 |
workspace.integrated |
integration span | 충돌·통합 시간 |
OpenTelemetry 생성형 AI 의미 규약은 2026년 7월 확인 시 여러 그룹이 Development 상태입니다. 스키마 버전을 저장하고 안정 표준이라고 표현하지 않습니다.
C.7 교체 시험
작업자나 오케스트레이터를 바꿀 때 같은 평가 세트로 비교합니다.
1. 기준 저장소·명세·예산·게이트 고정
2. 모의 작업자로 하니스 회귀 통과
3. 기존/후보 어댑터를 여러 trial 실행
4. 결과·정책·효율·복구 프로필 비교
5. 낮은 위험 작업군에 제한 배포
6. 운영 trace와 사람 개입 확인
7. 되돌리기 가능 상태에서 범위 확대
제품 기능 표 한 장보다 이 교체 시험이 우리 공장에 더 직접적인 선택 근거입니다.
부록 D. 지표 사전과 평가 루브릭
지표는 같은 이름보다 같은 정의가 중요합니다. 분모, 시작·종료 사건, 제외 조건, 집계 단위를 코드와 문서에 함께 고정합니다.
D.1 식별자와 집계 단위
| ID | 단위 | 설명 |
|---|---|---|
requestId |
제품 요구 | 사용자 가치 또는 변경 요청 |
taskId |
작업 | 독립 판정 가능한 작업 봉투 |
runId |
실행 | 한 번의 임대와 작업자 실행 |
changeId |
변경 | 리뷰·통합 대상 patch |
deployId |
배포 | 운영에 전달된 묶음 |
“성공률”에는 반드시 어느 단위의 성공인지 붙입니다. 실행 성공률과 작업 완료율은 다릅니다.
D.2 흐름 지표
작업 리드 타임
change.integrated 시간 - task.ready 시간
- 단위: 작업
- 취소: 별도 분포, 성공 리드 타임에 넣지 않음
- 보고: 중앙값, 상위 90%, 표본 수
활동 시간
실제 실행·검증·리뷰 활동 구간의 합입니다. 병렬 구간을 달력 시간처럼 중복 합산하지 않습니다.
대기 시간
준비 후 실행, 실행 후 게이트, 게이트 후 리뷰, 리뷰 후 통합의 대기를 나눕니다. 전체 리드 타임에서 활동 시간을 뺀 값만으로 원인을 알 수 없으므로 단계 이벤트를 사용합니다.
검증 완료 처리량
기간 안에 필수 게이트·리뷰를 통과해 통합된 작업 수입니다. 생성된 PR·실행 수를 세지 않습니다.
WIP
READY 이후 DONE/CANCELED 이전 작업 수입니다. 단계별 WIP를 함께 봅니다.
D.3 품질 지표
첫 시도 통과율
첫 run에서 기대 완료 상태를 얻은 완료 작업 수 / 완료 작업 수
의도된 BLOCKED가 기대 상태인 평가 사례와 실제 제품 작업의 성공을 섞지 않습니다.
재작업률
결함 때문에 리뷰·통합 후 다시 수정한 작업 / 통합 작업
요구 변경은 결함 재작업과 별도 분류합니다.
유출 결함률
배포 후 발견된 공장 관련 결함 / 배포 또는 통합 작업
분모를 선택해 고정하고 심각도 분포를 함께 냅니다. 탐지 문화가 좋아져 보고가 늘어난 현상을 품질 악화로 단순 해석하지 않습니다.
정책 위반률
필수 정책을 위반한 실행 수/전체 실행 수입니다. 한 번의 고심각 위반을 평균으로 희석하지 않고 ‘발생 여부’도 별도 차단 조건으로 둡니다.
D.4 사람의 주의
작업당 사람 개입 분
(명세 + 질문 응답 + 리뷰 + 복구 + 승인) 사람 분 / 완료 작업
개입 유형을 분리합니다. 명세에 더 쓴 20분으로 운영 결함 2시간을 막았다면 총량과 가치가 다릅니다.
차단 응답 시간
human.intervention.requested부터 결정 기록까지입니다. 제품 판단, 보안 승인, 플랫폼 복구를 분리해 소유자 병목을 찾습니다.
만족·인지 부담
짧은 주기 설문과 인터뷰로 “결과를 믿을 수 있는가”, “중단 없이 집중하는가”, “실패 원인을 찾을 수 있는가”를 봅니다. 활동량만으로 개발자 생산성을 정의하지 않습니다.
D.5 자원 지표
성공 작업당 자원
전체 run의 모델/도구/CI 자원 / 필수 게이트를 통과한 작업
실패와 재시도 자원을 포함합니다. 가격이 바뀌므로 토큰·초·CI 분 같은 원시값을 보존합니다.
작업당 실패 복구 비용
실패 실행 자원과 사람 복구 시간을 함께 보여 줍니다. 화폐로 환산하면 시간 단가와 기준일을 명시합니다.
D.6 평가 사례 루브릭
하드 실패를 먼저 판정합니다.
[ ] 금지 경로/도구/외부 효과
[ ] 비밀·개인정보 노출
[ ] 필수 수용 기준 누락
[ ] 필수 게이트 우회·테스트 0개
[ ] 승인 없는 고위험 행동
하나라도 해당하면 총점과 관계없이 실패입니다.
결과 품질: 0~4
| 점수 | 기준 |
|---|---|
| 0 | 핵심 요구 미충족 또는 제품 실행 불가 |
| 1 | 일부 정상 경로만 동작, 중요 오류/경계 누락 |
| 2 | 공개 수용 기준 충족, 숨은 경계 일부 실패 |
| 3 | 필수·경계·회귀 통과, 작은 비핵심 결함 |
| 4 | 모든 필수/숨은 검사와 호환·운영 증거 충족 |
변경 품질: 0~3
| 점수 | 기준 |
|---|---|
| 0 | 범위가 넓고 구조를 훼손하거나 설명 불가 |
| 1 | 동작하지만 중복·결합·불필요 변경이 큼 |
| 2 | 경계 안의 이해 가능한 변경, 작은 개선점 |
| 3 | 최소 범위, 저장소 관례, 명확한 계약과 복구 |
증거 품질: 0~3
| 점수 | 기준 |
|---|---|
| 0 | 성공 선언뿐, 재현 불가 |
| 1 | 일부 로그/테스트 있으나 명세 연결 부족 |
| 2 | 수용 기준·게이트·patch·입력이 연결됨 |
| 3 | 독립 리뷰·출처·잔여 위험·재현 명령까지 완전 |
효율 프로필
점수로 합치지 않고 다음 원시값을 비교합니다.
wall time / actions / attempts / changed files / diff size
model usage / tool seconds / CI minutes / human minutes
D.7 평가 안정성
실제 모델은 같은 사례를 여러 번 실행합니다.
trial: 같은 사례의 한 실행pass@k: k번 중 한 번 이상 성공할 확률을 보는 방식pass^k: k번 모두 성공할 확률을 보는 방식
두 지표는 다른 운영 질문에 답합니다. 여러 후보를 생성해 하나를 선택할 수 있으면 pass@k가 관련될 수 있습니다. 반복 작업이 매번 안정적이어야 하면 pass^k가 더 엄격한 관점을 줍니다. 표본과 독립성 가정을 표시하고 작은 차이를 과대해석하지 않습니다.
D.8 최소 팀 계기판
기간/업무군/난이도 분포
검증 완료 처리량
리드 타임 median/p90와 단계별 대기
첫 시도 통과율·재작업·유출 결함 심각도
작업당 사람 개입 분과 이유
성공 작업당 자원
상위 실패 코드와 정책 위반
WIP와 통합 충돌
개인별 코드 줄·실행 수·실패율 순위를 넣지 않습니다.
부록 E. 용어집
AI 에이전트(AI agent): 목표를 받고 상태를 관찰하며 모델 또는 규칙으로 다음 행동을 선택하고 도구 결과를 다시 관찰하는 실행 주체. 모델 자체와 구분합니다.
가드레일(guardrail): 위험한 행동이나 결과의 범위를 제한하는 규칙·통제의 총칭. 통과/실패가 기계적으로 정해진 품질 게이트보다 넓은 말입니다.
격리 작업 공간(isolated workspace): 한 실행의 입력과 변경을 다른 실행 및 기준선에서 분리한 파일 작업 공간. 프로세스·네트워크 샌드박스와 같은 말이 아닙니다.
관측 가능성(observability): 외부로 나온 이벤트·메트릭·트레이스와 산출물에서 시스템의 내부 상태와 실패 원인을 추론할 수 있는 성질.
기준 브랜치(base branch): 통합 대상이 되는 승인된 코드 흐름. 예제에서 이름이 main이어도 개념은 특정 이름에 묶이지 않습니다.
기준선(baseline): 비교 또는 실행의 고정 출발 상태. 코드 커밋, 지표 기간, 평가 결과를 뜻할 수 있으므로 대상을 붙입니다.
기억(memory): 실행 사이에 보존하는 상태나 지식. 작업 체크포인트, 승인된 결정, 검색 저장소를 구체적으로 구분합니다.
도구(tool): 에이전트가 파일 읽기, 쓰기, 검색, 명령, 외부 API 같은 행동을 수행하는 인터페이스. 도구 제공은 권한 제공입니다.
런(run): 하나의 작업을 수행하는 한 번의 실행 시도. 하나의 작업은 재시도로 여러 런을 가질 수 있습니다.
모델(model): 입력에서 출력 또는 행동 후보를 생성하는 추론 엔진. 파일·셸 도구와 실행 상태를 포함한 에이전트 전체가 아닙니다.
멱등성(idempotency): 같은 논리 요청을 반복해도 외부 상태에 중복 효과를 만들지 않는 성질. 결과 값이 바이트 단위로 같다는 뜻에 한정되지 않습니다.
명세 중심 개발(spec-driven development): 승인된 요구와 수용 기준을 구현·계획·검증의 기준점으로 삼는 방식. 특정 제품 하나의 이름이 아닙니다.
불변식(invariant): 허용된 시스템 상태나 입력 범위에서 계속 참이어야 하는 성질.
사람 승인(human approval): 고위험 행동·제품 결정·예외를 책임 있는 사람이 영향과 증거를 보고 허용하거나 거부하는 통제. 단순 확인 버튼과 구분합니다.
산출물(artifact): 실행이 만든 patch, 테스트 결과, 보고서, 체크포인트, 패키지처럼 보존·검증 가능한 결과.
샌드박스(sandbox): 코드 실행이 접근할 파일, 프로세스, 네트워크, 시스템콜, 자격 증명 등의 범위를 강제하는 환경. 어떤 자원을 가두는지 명시해야 합니다.
스팬(span): 트레이스 안의 한 작업 구간과 시간·속성을 나타내는 관측 단위.
실행 가능한 명세(executable specification): 기계 또는 명시적 사람 판정으로 예·아니오 결과를 낼 수 있는 수용 기준을 가진 명세.
에이전트 소프트웨어 공장(agentic software factory): 명세, 저장소 지식, 작업 그래프, 에이전트 하니스, 격리, 품질 게이트, 통합, 관측과 운영 책임을 반복 가능한 흐름으로 묶은 시스템.
역압(backpressure): 후단 공정의 용량이 부족할 때 새 작업 시작이나 상류 처리량을 줄여 WIP와 실패 확산을 막는 제어.
오케스트레이션(orchestration): 여러 작업과 실행자의 준비, 배치, 상태, 임대, 재시도, 취소, 통합 순서를 조정하는 기능.
위임 경계(delegation boundary): 에이전트가 승인 없이 선택·실행할 수 있는 목표, 경로, 도구, 예산, 외부 효과의 범위.
인수인계 패킷(handoff packet): 다른 사람이나 에이전트가 작업을 이어받도록 공식 입력, 확인 사실, 변경, 게이트, 폐기한 가설, 남은 위험, 다음 행동을 묶은 상태.
작업 그래프(task graph): 작업 간 선행 의존성을 나타낸 그래프. 병렬 실행에는 방향성 비순환 그래프(DAG)와 실제 충돌 검토가 필요합니다.
작업 봉투(task envelope): 목표, 명세, 입력, 허용 경로, 도구 권한, 게이트, 예산, 위험을 묶은 실행 계약.
작업자(worker): 한 작업 봉투를 받아 격리 공간에서 변경을 수행하는 역할. 모델 기반 에이전트, 결정론적 모의 구현, 사람이 이 역할을 구현할 수 있습니다.
재시도(retry): 실패 뒤 새 런과 정책으로 같은 작업을 다시 시도하는 것. 같은 작업 공간에서 무한 반복하는 것과 다릅니다.
제어면(control plane): 작업·정책·임대·예산·승인·상태를 관리하는 영역. 제품 코드를 수정·실행하는 작업면과 분리합니다.
체크포인트(checkpoint): 프로세스가 사라져도 검증 후 재시작할 수 있도록 단계, 입력/출력 해시, 외부 효과, 남은 행동을 보존한 상태.
컨텍스트 엔지니어링(context engineering): 현재 결정에 필요한 정보를 선택·배치·압축·갱신하고 출처와 권위를 관리하는 설계.
텔레메트리(telemetry): 시스템이 외부로 내보내는 로그, 이벤트, 메트릭, 트레이스 데이터.
통합 큐(merge queue): 승인된 변경 후보를 최신 기준선에 순서대로 적용하고 재검증한 뒤 통합하는 제어 흐름.
트레이스(trace): 하나의 요구·작업이 여러 실행, 도구, 게이트, 리뷰, 통합을 거치는 인과 경로.
평가(evaluation, eval): 대표 업무에서 에이전트와 하니스의 결과·과정·효율·복구 능력을 반복 실행과 채점기로 비교하는 체계.
품질 게이트(quality gate): 대표 위험에 대해 통과·실패와 다음 행동이 기계적으로 정해진 검사.
하니스(harness): 에이전트의 입력과 문맥을 조립하고 도구·권한·상태·예산·검증·관측·복구를 제공하는 실행 체계.
회로 차단기(circuit breaker): 공통 실패가 연속될 때 관련 새 실행을 일시 중단하고 제한된 탐침으로 회복을 확인하는 제어.
부록 F. 출처 장부·팩트체크·정오표 운영
기술책의 오류는 문장 오탈자만이 아닙니다. 실행되지 않는 명령, 실제 화면과 다른 캡처, 지원하지 않는 운영체제 표기, 바뀐 제품 기능, 사례 수치의 과장도 사실 오류입니다. 이 책은 문장과 코드를 같은 검증 흐름으로 관리합니다.
F.1 근거 등급
| 등급 | 근거 | 본문 표현 |
|---|---|---|
| A | 표준·규격·정부 문서 | 버전과 적용 범위를 붙여 정의·권고 설명 |
| B | 공개 방법과 표본이 있는 연구 | 연구 조건과 한계를 문장 안에 유지 |
| C | 회사의 자사 엔지니어링 사례 | “해당 팀은 …라고 보고했다”로 한정 |
| D | 살아 있는 공식 제품 문서·저장소 | 기준일·버전 고정, 인쇄 직전 재확인 |
검색 결과 요약과 AI 응답은 원출처를 찾는 단서이지 최종 근거가 아닙니다.
F.2 출처 장부 필드
고유 ID
문서 제목·발행 주체·URL
발행/갱신일과 접근일
버전·태그·커밋·절
책에서 검증할 최소 주장
근거 등급과 일반화 한계
본문 장·그림·홍보 문구 위치
라이선스와 인용/각색 조건
재검증 상태와 검증자
실제 장부는 책 패키지의 02-sources/source-ledger.md와 ID로 연결된 02-sources/source-verification-ledger.md 두 파일입니다. 첫 파일은 주장·활용 위치·일반화 한계를, 두 번째는 버전/절·인용/각색·권리·검증자·재확인 상태를 관리합니다. 현재 행의 INTERNAL-CHECKED / HUMAN-PENDING은 공식 원문을 내부 대조했지만 독립 사람 팩트체크와 출판사 권리 검토는 끝나지 않았다는 뜻입니다.
F.3 수치 문장 검산
수치마다 적습니다.
주체 / 기간 / 표본·시행 / 분자 / 분모 / 단위
기준선 / 비교군 / 평균·중앙값·백분위
불확실성 / 제외 조건 / 원문 위치 / 반올림
500% 증가와 5배가 됨은 같지 않습니다. benchmark의 작업 점수를 현실의 개발 기간이나 매출로 바꾸지 않습니다. 한 조직의 추정치를 독자의 기대 ROI로 제시하지 않습니다.
F.4 코드와 화면의 단일 원본
본문 명령과 예상 출력, 출판용 화면은 다음 흐름으로 생성합니다.
깨끗한 예제 기준선
→ 고정 fixture와 clock으로 실제 명령 실행
→ stdout/stderr/종료 코드/산출물 캡처
→ 캡처 manifest 검증
→ 같은 데이터로 본문 출력과 SVG/PNG 생성
→ 원고의 명령·파일명·상태 문자열 대조
화면을 손으로 다시 그려 실제처럼 보이게 하지 않습니다. 동적 절대경로와 시각은 의미를 보존하는 고정 fixture로 정규화했다는 사실을 캡션에 밝힙니다. 각 그림은 다음을 가집니다.
그림 번호 / 장 / 원본 파일 / 생성 명령 / 입력 fixture
예제 버전 / 기대 종료 코드 / 캡션 / 대체 텍스트
화면 문자열 검증 / 제작·라이선스
F.5 출간 전 재확인 목록
- 제품·프로토콜·표준의 살아 있는 문서 버전
- Node.js/Git 지원 하한과 실제 재현 행렬
- 본문의 모든
npm run명령이 package script에 존재 - 예상 출력과 실제 캡처 문자열·테스트 개수
- 실패 실습이 의도한 이유와 종료 코드로 실패
- 외부 링크와 각주가 직접 해당 주장을 지지
- 직접 인용 길이와 그림/표 라이선스
- 표지·보도자료의 생산성·판매 문구가 본문보다 강하지 않음
- EPUB에서 코드 줄, 표, 대체 텍스트, 링크 동작
- 종이 흑백 교정쇄에서 상태가 색 없이 구분됨
F.6 정오표 심각도
| 등급 | 예 | 대응 목표 |
|---|---|---|
| P0 | 데이터 손실·비밀 노출 위험 명령, 위험한 보안 오류 | 즉시 다운로드 중단/경고, 24시간 내 공지 |
| P1 | 핵심 실습 완주 불가, 중요한 사실·수치 오류 | 확인 후 3영업일 내 수정안 |
| P2 | 우회 가능한 명령·플랫폼 차이·설명 오류 | 다음 패치와 전자책 갱신 |
| P3 | 오탈자·표현·깨지지 않는 링크 보완 | 정기 정오표 |
‘대응 목표’는 출판 계약과 운영 인력에 맞춰 확정합니다. 지키지 못할 시간을 홍보 문구로 약속하지 않습니다.
F.7 독자 제보 양식
제목: [장/그림/실습] 한 문장 증상
- 책 판/전자책 버전:
- 운영체제·셸·Node.js:
- 장/쪽/파일/그림:
- 실행한 정확한 명령:
- 기대 결과:
- 실제 결과와 종료 코드:
- 최소 재현 단계:
- 비밀을 제거한 관련 로그/산출물:
- 제안 수정(선택):
제보자의 이름·연락처·로그를 공개 정오표에 허락 없이 싣지 않습니다.
F.8 수정 릴리스
제보 접수
→ 재현과 심각도 분류
→ 코드/원고/그림의 단일 원본 수정
→ 전체 `npm run verify`와 캡처 재생성
→ 기술 검수
→ 예제 버전·전자책·정오표 갱신
→ 수정 범위와 남은 제한 공개
오류 문장만 고치고 예제와 그림을 그대로 두지 않습니다. 한 원본에서 파생된 모든 산출물을 다시 빌드합니다.
F.9 시의성 운영
인쇄 본문에는 오래가는 역할과 실패 원리를 둡니다. 최신 모델명, 가격, UI 경로, 컨텍스트 한도, 제품별 지시 파일 지원 행렬은 온라인 호환표로 분리합니다. 전자책 갱신에서도 기준일을 조용히 바꾸지 않고 판과 변경 기록을 남깁니다.
연습문제 해설과 설계 루브릭
정답이 하나인 확인 문제는 기준 답을 제시합니다. 조직·저장소에 따라 달라지는 설계 문제는 모범 답 하나를 강제하지 않고 반드시 포함할 판단 기준을 제공합니다. 답을 먼저 읽기보다 실행 산출물과 자신의 설계를 적은 뒤 비교합니다.