07. 실전 — 예제 프로젝트를 agent와 나눠 만들기
06이 추상 루프라면, 07은 “실제로 터미널에 무엇을 치는가” 다. 빈 폴더에서 시작해 배포 직전까지, 한 기능을 명령 단위로 따라간다. 각 단계마다 🧑(사람이 결정·책임)와 🤖(agent가 실행)를 표시하고, 4개의 게이트에서 멈춘다.
- 비교: examples/walkthrough-password-reset.md는 의사결정 흐름을, 이 문서는 명령·절차를 보여준다.
- 두 트랙을 함께 제시한다: (A) SpecKit 사용 / (B) SpecKit 없이 순수 Claude Code. 도구가 없어도 같은 원리로 할 수 있다. → 03
예제 프로젝트
URL 단축기 API. 작지만 4축을 모두 건드린다:
- POST
/links {url}→ 7자리 base62 단축 코드 반환 - GET
/{code}→ 원본으로 302 리다이렉트 - 잘못된 URL → 400, 없는 코드 → 404
- DB가 필요(되돌림·파급 높음 → 사람 게이트), 배포가 있음(게이트 4)
스택은 일부러 게이트 2에서 사람이 결정한다(아래). 예시에서는 Python + FastAPI + SQLite로 진행한다.
게이트 0 — 준비: 환경과 가드레일 〔🧑〕
먼저 사람이 저장소와 가드레일을 깐다. 이건 위임하지 않는다.
mkdir url-shortener && cd url-shortener
git init
(A) SpecKit 사용 — Claude Code 연동으로 초기화 (설치/명령은 03 참고):
uv tool install specify-cli --from git+https://github.com/github/spec-kit.git
specify init . --integration claude # .specify/ 와 슬래시 명령 설치
그다음 Claude Code를 켜고 헌법을 만든다:
/speckit.constitution # 🤖 초안 → 🧑 원칙 확정 (.specify/memory/constitution.md)
(B) SpecKit 없이 — 폴더와 CLAUDE.md만 직접 만든다:
mkdir -p docs/specs docs/adr
Claude Code 안에서:
/init # 🤖 CLAUDE.md 초안 생성 → 🧑 빌드/테스트 명령·규칙 보강
→ 어느 트랙이든 헌법 템플릿의 원칙(테스트 없는 머지 금지, DB/배포는 사람 게이트 등)을 CLAUDE.md 또는 constitution.md에 박는다. 이게 agent가 못 넘는 하드 가드레일이다.
게이트 1 — Spec: 무엇을 만드나 〔🧑 주도 + 🤖 초안·질문〕
(A) SpecKit:
/speckit.specify URL을 받아 7자리 단축 코드를 만들고, 코드로 원본에 리다이렉트하는 API.
/speckit.clarify # 🤖 모호한 점을 질문 → 🧑 답하면 spec.md에 반영
(B) 순수 Claude Code: PRD/Spec 템플릿을 주고 초안을 시킨다.
docs/specs/url-shortener.md 를 templates/01-prd.md 형식으로 채워줘.
수용 기준은 테스트로 옮길 수 있게 측정 가능하게 쓰고,
모호한 점은 "미해결 질문"에 나열만 하고 임의로 결정하지 마.
🧑 사람은 agent의 질문에 답하며 수용 기준을 측정 가능하게 확정한다(이게 TDD와의 다리 → 02):
- 코드는 7자 base62, 충돌 시 재생성
url이 http/https가 아니면 400- 없는 코드는 404
- 같은 URL을 또 넣으면 같은 코드를 재사용한다 / 안 한다 ← 🧑가 판단해 못 박기
git add -A && git commit -m "spec: url-shortener 요구사항 확정"
⛔ 게이트 1 — spec 승인. 사람이 spec을 읽고 OK 하기 전에는 다음 단계로 가지 않는다. 여기서 틀리면 이후 전부 틀린다.
게이트 2 — Plan & 아키텍처: 어떻게 〔🤖 옵션 제시 + 🧑 결정〕
핵심: 코드를 짜기 전에 plan mode를 켠다. Claude Code에서 Shift+Tab으로 모드를 순환해 plan mode로 들어가면, agent가 코드를 건드리지 않고 계획만 제시한다. (best practices)
🤖 agent가 옵션·트레이드오프를 제시하고, 🧑 사람이 결정한다:
- 스택: FastAPI vs Flask vs Node/Express → 🧑 FastAPI 선택
- 코드 생성: 랜덤 base62 vs ID 해시 → 🧑 랜덤 + 충돌 시 재시도
- 저장소: SQLite vs Postgres → 🧑 SQLite(MVP)
되돌리기 어려운 결정은 ADR로 남긴다:
docs/adr/0001-stack-and-storage.md 를 templates/03-adr.md 형식으로 작성해.
결정: FastAPI + SQLite, 랜덤 base62 코드. 맥락과 포기한 것을 적어.
(A) SpecKit:
/speckit.plan FastAPI + SQLite. 랜덤 7자 base62 코드, 충돌 시 재시도.
/speckit.analyze # 🤖 spec ↔ plan ↔ tasks 일관성 교차 검증 → 🧑 리포트 확인
git add -A && git commit -m "plan: 아키텍처 결정 + ADR-0001"
⛔ 게이트 2 — plan/아키텍처 승인. 아키텍처는 되돌림·파급이 높은 결정이 모이는 곳이라 사람이 반드시 승인한다.
게이트 3 직전 — Tasks & 구현 〔🤖 주도(TDD) + 🧑 게이트〕
작업 분해 〔🤖 주도, 🧑 검토〕
/speckit.tasks # (A) tasks.md 생성
# (B) 순수: "templates/04-tasks.md 형식으로 작업을 의존성 순서대로 쪼개줘"
생성된 tasks에서 🧑 사람은 사람 게이트가 필요한 작업에 ⚠️ 표시가 됐는지 검토한다:
- T1. DB 스키마·마이그레이션 — ⚠️ 사람 게이트(DB)
- T2. 코드 생성기 실패 테스트 → 구현
- T3. POST
/links테스트 → 구현 - T4. GET
/{code}리다이렉트 테스트 → 구현 - T5. 엣지(400/404/충돌) 테스트 → 구현
구현 — TDD 루프 〔🤖〕
/speckit.implement # (A) 모든 작업을 계획대로 실행
(B) 순수 Claude Code에서는 작업을 하나씩, TDD를 강제하며 시킨다:
T2를 진행해. 먼저 실패하는 테스트부터 쓰고(Red), 통과시키고(Green), 정리해(Refactor).
구현이 아니라 테스트를 약화시켜 통과시키지 마.
- ⚠️ T1(마이그레이션)은 사람이 검토 후 실행한다 — agent가 자동 적용하지 않게 막는다. (헌법/permission mode로 강제)
- 큰 탐색(많은 파일 읽기)은 subagent에 위임해 메인 컨텍스트를 깨끗이 유지.
- 작업을 바꿀 때는
/clear로 컨텍스트를 리셋(컨텍스트 열화 방지).
🧑 사람은 통과 여부만 보지 말고 테스트가 올바른 것을 검증하는지 확인한다(예: “없는 코드 → 404” 테스트가 실제로 404를 검사하는가). → 02. TDD의 함정
게이트 3 — diff 리뷰 〔🧑〕
git diff # 변경 전체 훑기
# 또는 PR을 만든다면:
git switch -c feat/url-shortener && git push -u origin feat/url-shortener
🧑 04. 경계대로 모든 줄이 아니라 위험한 곳에 집중한다: 입력 검증(400), 리다이렉트 대상(오픈 리다이렉트 위험), DB 쿼리. 단순·검증성 높은 부분(코드 생성기)은 테스트 통과로 신뢰한다.
git commit -am "feat: url-shortener 구현" && git merge --no-ff feat/url-shortener
⛔ 게이트 3 — diff 리뷰. 사람이 보고 승인하기 전엔 머지하지 않는다.
게이트 4 — 배포 〔🧑〕
# 예: 컨테이너 빌드 후 배포 (스택·플랫폼에 맞게)
docker build -t url-shortener . && <배포 명령>
⛔ 게이트 4 — 배포 승인. 되돌림·파급이 최고인 단계. 항상 사람이 승인한다. permission mode로 배포성 명령을 게이트로 묶어 두면 agent가 임의 실행하지 못한다.
전체 흐름 치트시트
게이트 0 🧑 git init · specify init · /speckit.constitution(또는 /init)
─────────────────────────────────────────────────────────────
스펙 🤖→🧑 /speckit.specify → /speckit.clarify
⛔ 게이트 1: spec 승인
─────────────────────────────────────────────────────────────
계획 🤖→🧑 Shift+Tab(plan mode) · /speckit.plan · ADR 기록 · /speckit.analyze
⛔ 게이트 2: plan/아키텍처 승인
─────────────────────────────────────────────────────────────
작업 🤖→🧑 /speckit.tasks (⚠️ DB/배포 게이트 표시 검토)
구현 🤖 /speckit.implement (TDD, T1 마이그레이션은 사람 실행)
⛔ 게이트 3: git diff 리뷰 → 머지
─────────────────────────────────────────────────────────────
배포 🧑 사람 승인 후 릴리스
⛔ 게이트 4: 배포 승인
신뢰가 쌓이고 테스트·CI로 검증성이 올라가면, 게이트 1·2를 가볍게 통과시키고 in-the-loop → on-the-loop로 물러난다. 게이트 3·4(되돌림·파급 높음)는 끝까지 사람이 쥔다.
처음부터 SpecKit·ADR·헌법을 다 갖출 필요는 없다. 06의 “최소 실천”처럼
CLAUDE.md+ plan mode + diff 리뷰 3가지로 시작하고, 모호함·협업이 늘면 이 절차를 채워 나가라.