AI로 하는 스펙 주도 개발: 코드보다 계획을 먼저 쓰기 (2026)
스펙 주도 개발(SDD)은 스펙을 유일한 진실 공급원(single source of truth)으로 삼는 방법입니다. 먼저 수용 기준이 담긴 스펙과 계획을 먼저 작성하고, 그다음 AI 에이전트가 그에 맞춰 코드와 테스트를 생성하게 합니다. "바이브만"(얇은 프롬프트 하나 던지고 잘되길 바라는 방식)과 비교하면, SDD는 AI가 요구사항에서 벗어나거나, 아키텍처를 이탈해 헤매거나, 끝없는 재작업 루프에 토큰을 낭비하는 경우를 크게 줄여줍니다. 이 글에서는 그대로 복사해 쓸 수 있는 진짜 spec.md와 plan.md를 드리고, 그 루프를 Claude Code 안에서 어떻게 돌리는지 보여드릴게요.
스펙 주도 개발이란?
스펙 주도 개발은 명세(spec)를 유일한 진실 공급원으로 삼는 방법입니다. 첫 줄의 코드를 쓰기 전에 "무엇을, 왜 만들어야 하며, 완료란 어떤 모습인지"를 적어두고, 그다음 AI 에이전트가 그 스펙을 따르는 코드·테스트·문서를 생성하게 합니다. 한마디로, AI가 당신의 의도를 추측하는 대신 스펙이 AI를 움직이게 하는 것입니다.
핵심은 바로 그 표현, "유일한 진실 공급원"입니다. 예전 방식에서는 요구사항이 당신의 머릿속, 몇 개의 채팅 메시지, 그리고 얇은 티켓에 흩어져 있습니다. AI는 그중 아주 일부만 읽을 수 있어서 나머지를 추론할 수밖에 없고, 추론이 바로 버그가 태어나는 곳입니다. SDD는 사람도 에이전트도 읽을 수 있는 하나의 문서에 중요한 제약을 전부 모으도록 강제합니다. 목표, 범위, 수용 기준, 그리고 일부러 하지 않기로 한 것들(비목표)까지요.
이것은 "코드를 짜기 전에 거대한 문서를 쓰라"는 워터폴로의 회귀가 아닙니다. SDD의 스펙은 짧고, 살아 있으며, 보통 화면 한두 개 분량밖에 되지 않습니다. 그것은 코드에 앞선 컨텍스트입니다. 똑똑한 에이전트가 한 번에 제대로 해내기에 딱 충분한 컨텍스트이며, 당신이 나중에 서너 번씩 손으로 고치는 것을 대신합니다. Thoughtworks는 이것을 AI로 소프트웨어를 작성하는 방식을 다시 짜고 있는 패턴이라고 말합니다(Thoughtworks, 2025).
왜 계획을 먼저 쓰는 것이 "바이브만"을 이기는가?
"바이브만"의 핵심 문제에 기억하기 쉬운 이름을 붙여봅시다. "모호성 세금(ambiguity tax)"입니다. 요구사항이 아직 흐릿한 모든 지점에서 AI는 빈칸을 채우도록 강요당합니다. AI는 그것을 당신의 실제 의도가 아니라, 학습 데이터에서 끌어낸 평균적인 추측으로 채웁니다. 당신은 그 세금을 재작업 루프의 형태로 되갚게 됩니다. "아니, 그런 뜻이 아니야", "이 케이스를 빠뜨렸어", "왜 상관없는 파일까지 통째로 바꿨어?" 같은 식으로요.
AI에게 맡기고 주도하게 하는 손 떼는 방식이 처음이라면, 맥락을 위해 먼저 vibe coding이 무엇인지를 읽어보세요. SDD는 vibe coding을 거부하는 것이 아니라 그 위에 규율을 얹는 단계입니다. "바이브만"은 빠른 탐색에는 훌륭하지만, 작업에 명확한 요구사항이 생기는 순간 세 가지 위험을 드러냅니다.
- 요구사항 드리프트: AI가 돌아가긴 하지만 당신이 필요로 한 것은 아닌 무언가를 내놓습니다. 엣지 케이스 누락, 비즈니스 로직 오독, 당신의 관례를 깨는 네이밍과 인터페이스 같은 것들이죠.
- 아키텍처 드리프트: 모든 프롬프트가 즉흥적인 설계 결정이 됩니다. 프롬프트를 열 번 쌓으면 코드베이스는 아무도 의도적으로 설계하지 않은 누더기가 됩니다.
- 불어나는 토큰 비용: "이거 다시 고쳐줘"라는 루프마다 에이전트는 컨텍스트를 다시 읽고 코드를 다시 생성합니다. 서너 번의 재작업은 처음에 좋은 스펙 하나를 쓰는 것보다 몇 배의 토큰을 씁니다.
스펙 주도는 순서를 뒤집습니다. 아직 쌀 때, 맨 앞에서 "생각하는 비용"을 한 번만 치릅니다. 수용 기준을 쓰는 일은, AI가 아니면 추측해야 할 바로 그 질문에 당신이 직접 답하도록 강제합니다. 일단 컨텍스트가 명확해지면 에이전트가 잘못 추측할 여지는 거의 남지 않습니다. 성숙한 vibe coding 워크플로가 쉬지 않고 프롬프트만 던지는 대신 언제나 중간에 계획 작성 단계를 엮어 두는 이유도 이것입니다.
spec vs plan vs task ― 무엇이 다른가?
이 세 단어는 자주 뭉뚱그려지지만, 그 사이에 깔끔한 선을 긋는 것이 SDD의 핵심입니다. 한마디로, spec은 "무엇을, 왜"에, plan은 "어떻게, 어떤 순서로"에, task는 실행의 최소 단위에 답합니다.
| 요소 | 답하는 것 | 담는 내용 | 주 독자 |
|---|---|---|---|
| Spec | 무엇을·왜 | 목표, 범위, 수용 기준, 비목표, 엣지 케이스 | 사람+AI가 함께 리뷰 |
| Plan | 어떻게, 어떤 순서로 | 순서가 있는 단계, 손댈 파일, 테스트 방법, 위험/롤백 | AI 에이전트가 실행 |
| Task | 다음에 할 구체적인 일 | 한 번에 끝나고 검증 가능한 작은 단위 하나 | 에이전트(또는 당신)가 하나씩 수행 |
흔한 혼동: "어떻게"를 spec에 욱여넣거나(스펙이 너무 이른 단계에서 시시콜콜 관리되어 유연성을 잃음), 수용 기준을 건너뛴 plan을 쓰는 것(에이전트가 언제 완료라고 불러도 되는지 알 수 없음)입니다. 선을 지키는 요령: 답이 "사용자나 시스템이 필요로 하는 것"에 관한 것이면 spec에, "무엇을 입력하는지, 어떤 파일을 먼저 편집하는지"에 관한 것이면 plan에 속합니다.
진짜 예시: 코드에 앞선 spec + plan
이론은 이만하면 충분합니다. 제가 이걸 설명할 때 자주 쓰는 작은 기능의 진짜 산출물이 여기 있습니다. 로그인 엔드포인트에 속도 제한(rate limit) 추가입니다. 이 두 파일을 복사하고 프로젝트에 맞게 몇 줄만 손보면 바로 쓸 수 있어요. 먼저 spec.md입니다. 이것은 "무엇을, 왜"만 말하고, 어떻게는 절대 말하지 않습니다.
# spec.md - Rate limit for the login API
## Goal
Block brute-force against POST /api/login by limiting the number of
attempts per IP + email, returning a clear error when the limit is passed.
## Why
Login currently has no limit -> passwords are easy to guess and the DB
can be overloaded.
## Acceptance criteria
- Max 5 failed attempts / 15 minutes per (IP, email) pair.
- Over the limit -> HTTP 429 + body { error: "too_many_attempts", retry_after }.
- A SUCCESSFUL login resets the counter for that (IP, email) pair.
- Automated tests for: under the limit, at the limit, over the limit, and reset.
## Non-goals
- NO CAPTCHA (deferred to a later phase).
- NO rate-limiting other endpoints this time.
## Edge cases
- Many users behind the same NAT/IP -> key on (IP, email), not IP alone.
- Clock/timezone: use UTC for the time window.
다음은 plan.md입니다. 이제, 그리고 이제서야 "어떻게, 어떤 순서로"를 말합니다. 손댈 파일 열과 롤백 섹션에 주목하세요.
# plan.md - Implementing login rate limit
## Steps (in order)
1. Add an attempt-counter store (Redis, key = login:{ip}:{email}, TTL 15m).
-> File: src/lib/rate-limit.ts (new)
2. Write a checkLoginRateLimit middleware that reads/increments the counter.
-> File: src/middleware/login-rate-limit.ts (new)
3. Attach the middleware to POST /api/login BEFORE the auth handler.
-> File: src/routes/auth.ts (edit)
4. On successful login -> delete the counter key for that (IP, email).
-> File: src/routes/auth.ts (edit)
5. Write tests for the 4 cases in the acceptance criteria.
-> File: tests/login-rate-limit.test.ts (new)
## How to test
- npm test tests/login-rate-limit.test.ts
- Manual: send 6 wrong requests in a row -> the 6th must return 429.
## Risk & rollback
- Redis down -> fail-open (let it through) or fail-closed? Choose fail-open +
log a warning, so infra failures do not lock out every user.
- Rollback: removing the middleware in step 3 returns the system to its
original state.
이 계획대로 AI를 돌리면 무슨 일이 벌어지는가: 에이전트는 올바른 순서로 작업하고, 모든 파일을 만들고, 수용 기준이 "완료"의 의미를 못 박아 두었기 때문에 올바른 지점에서 멈춥니다. 인증 모듈 전체를 아무렇지 않게 리팩터링하거나 카운터 리셋 케이스를 잊는 일은 더 이상 없습니다. 같은 에이전트, 같은 작업 ― 차이는 지도를 쥐고 있느냐뿐입니다.
AI와 함께하는 스펙 주도 워크플로(6단계)
이것은 제가 거의 모든 중대형 기능에 쓰는 루프입니다. brainstorm -> plan -> cook -> ship 워크플로에 거의 일대일로 대응합니다.
- 아이디어와 컨텍스트: 풀어야 할 문제와 진짜 제약(스택, 관례, 절대 건드리면 안 되는 것)을 적습니다. 여기가 프로젝트의 "진실"을 모으는 곳입니다.
- 스펙을 쓴다: 목표/비목표/수용 기준/엣지 케이스를 채웁니다. 수용 기준에서는 구체적이 되도록 스스로를 몰아붙이세요. 모호한 곳은 어디든 AI가 추측합니다.
- 스펙을 리뷰한다(사람+AI): 코드가 한 줄도 존재하기 전에, 에이전트에게 스펙을 읽히고 모순·빠진 케이스·불가능한 요구사항을 짚어내게 합니다.
- 계획을 쓰고 태스크로 쪼갠다: 스펙을, 손댈 파일과 테스트 방법과 롤백을 명시한 순서 있는 단계로 바꿉니다. 각 태스크가 한 번에 검증되도록 얇게 저밉니다.
- 에이전트가 태스크 단위로 코딩하게 한다: 한 번에 한 태스크씩 돌리고, 앞서가지 못하게 합니다. 각 태스크 뒤에는 에이전트가 자기 작업을 계획과 대조하게 하세요.
- 수용 기준에 대해 검증한다: 테스트를 돌리고 기준을 한 줄씩 짚어갑니다. 모든 기준이 초록불일 때에만 기능이 완료된 것입니다 ― "돌아가는 것처럼 보일" 때가 아니라요.
핵심은, 3단계와 6단계가 SDD가 당신을 가장 크게 구해주는 지점이라는 것입니다. 스펙 단계에서 버그를 잡는 것은 코드에서 잡는 것보다 수십 배 싸게 먹힙니다.
Claude Code 안에서 스펙 주도를 제대로 하기
시작하는 데 특별한 도구는 필요 없습니다. Claude Code에는 이미 군더더기 없는 SDD 루프를 세우기에 충분한 세 가지가 들어 있습니다.
- Plan Mode: Claude Code는 계획을 초안 잡고, 어떤 파일에 손대기 전에 당신이 승인하게 합니다 ― 바로 "계획 먼저, 코드는 나중" 정신 그대로입니다(Anthropic docs, 2026). 최대한 활용하는 방법은 Claude Code로 계획하기(Plan Mode)에서 보세요.
- 상시 가드레일로서의 CLAUDE.md: 오래 가는 관례·경계·비목표를 이 파일에 넣어두면 에이전트가 항상 그것을 읽습니다 ― 반복되는 제약을 저장소의 고정된 "진실"로 바꾸는 것이죠. 이것이 가장 단순한 형태의 context engineering입니다.
- GitHub Spec Kit: SDD를 명시적인 워크플로
/specify->/plan->/tasks로 바꿔주는 오픈소스 명령 모음으로, Claude Code를 비롯한 여러 에이전트와 함께 쓸 수 있습니다(GitHub Blog, 2025).
미리 만들어진 스펙 주도 워크플로를 원하세요? CLAUDE.md + Plan Mode + Spec Kit을 직접 손으로 배선하고 싶지 않다면, Claude Code용 AgentKit 번들 ― 지금 $149 (기존 $198)가 같은 spec -> plan -> code -> verify 흐름을 따르는 brainstorm/plan/cook/ship 스킬과 리뷰 서브에이전트를 묶어 줍니다. AgentKit란 무엇인가에 자세히 정리해 두었어요 ― 스스로 판단하려면 읽어보세요. 서둘러 구매할 필요는 없습니다.
2026년의 스펙 주도 도구
가벼운 것부터 완전히 패키지화된 것까지, 인기 있는 선택지 몇 가지.
| 도구 | 강점 | 이런 사람에게 |
|---|---|---|
| GitHub Spec Kit(OSS) | 명확한 워크플로 /specify /plan /tasks. 무료이고 여러 에이전트와 동작 | 하나의 IDE에 묶이지 않는 표준 SDD 관례를 원하는 사람 |
| Kiro IDE(AWS) | 에디터 안에서 spec/design/task를 생성하는 spec 우선 IDE | 하나로 완전히 통합된 환경을 선호하는 사람 |
| Claude Code + Plan Mode/CLAUDE.md | 추가 설치 불필요. 상시 가드레일. 코드 전에 계획 승인 | 이미 Claude Code를 쓰면서 지금 시작하고 싶은 사람 |
| AgentKit 워크플로 | brainstorm->plan->cook->ship 흐름+리뷰 서브에이전트를 패키지화 | 직접 배선하는 대신 미리 만들어진 프로세스를 원하는 사람 |
유일하게 "정답"인 도구는 없습니다. 대부분의 기능에는 순수 Markdown+Plan Mode로 충분합니다. 무거운 키트는 SDD를 자주 하고 팀 전체에서 표준화하고 싶을 때에만 값을 합니다.
스펙 주도가 필요 없을 때는 언제인가?
SDD는 도구이지 종교가 아닙니다. 모든 것에 스펙을 강요하면 역효과가 납니다. 다음의 경우에는 SDD를 건너뛰세요.
- 일회성 스크립트나 버릴 작업 ― 스펙을 쓰는 게 그냥 해버리는 것보다 더 오래 걸립니다.
- 탐색적 프로토타입/스파이크: 목표는 빨리 배우는 것이지 아직 제대로 만드는 것이 아닙니다. 이 단계에는 "바이브만"이 더 잘 맞습니다.
- 원인을 이미 아는 한 줄짜리 버그 수정 ― 한 글자를 바꾸는 데 수용 기준은 필요 없습니다.
- 한 시간마다 바뀌는 요구사항: 스펙이 쓰는 속도보다 빨리 낡아버립니다.
SDD가 잘 맞는 경우에도 조심할 함정이 둘 있습니다. 과잉 스펙(over-spec)(너무 상세한 스펙을 써서 뻣뻣해지고 유연성을 죽임)과 스펙 부패(spec rot)(코드가 바뀌어도 스펙이 갱신되지 않아 거짓말하는 문서가 됨)입니다. 좋은 스펙이란 에이전트가 제대로 해내기에 딱 충분하면서도 여전히 바꾸기 쉬운 것이지, 가장 긴 것이 아닙니다.
자주 묻는 질문(FAQ)
스펙 주도 개발은 vibe coding과 어떻게 다른가요?
vibe coding은 프롬프트를 던져 AI가 주도하게 하는 것으로, 빠른 탐색에 어울립니다. 스펙 주도는 어떤 코드보다 먼저 수용 기준이 담긴 스펙을 진실 공급원으로 세우는 것으로, 요구사항이 명확한 기능에 어울립니다. SDD는 vibe coding을 거부하는 게 아니라 규율을 더하는 단계입니다.
spec은 plan과 다른가요?
네. spec은 "무엇을, 왜"(목표, 범위, 수용 기준, 비목표)에 답합니다. plan은 "어떻게, 어떤 순서로"(단계, 손댈 파일, 테스트 방법, 롤백)에 답합니다. spec은 더 안정적이고, plan은 접근 방식이 바뀌면 바뀝니다.
전용 도구가 필요한가요, 아니면 Markdown으로 충분한가요?
시작하는 데는 순수 Markdown으로 충분합니다 ― spec.md와 plan.md만 있으면 됩니다. GitHub Spec Kit이나 Kiro 같은 도구는 SDD를 정기적으로, 혹은 팀 전체에서 하게 될 때에야 프로세스 표준화에 도움이 됩니다.
스펙 주도는 속도를 늦추나요?
처음엔 느리지만 전체적으로는 빠릅니다. 스펙을 쓰는 데 몇 분을 더 쓰지만, AI가 벗어났을 재작업 루프를 많이 줄입니다. 작고 버릴 작업에는 정말 값하지 않으니 ― 그럴 땐 그냥 바이브로 가세요.
스펙 주도를 Cursor나 Copilot과 함께 쓸 수 있나요?
네. SDD는 방법론이지 하나의 도구에 묶이지 않습니다. spec.md/plan.md를 저장소에 두고 어떤 에이전트(Claude Code, Cursor, Copilot)든 그것을 따르게 할 수 있습니다. GitHub Spec Kit은 애초에 멀티 에이전트로 쓰도록 설계됐습니다.
스펙은 얼마나 길어야 하나요?
에이전트가 중요한 무언가를 추측하지 않아도 될 만큼의 길이, 보통 화면 한두 개 분량입니다. 스펙이 그것이 만들어내는 코드보다 길다면 과잉 스펙입니다. 진짜 시금석은 명확한 수용 기준과 명확한 비목표입니다.
결론 + 다음 단계
원칙은 짧게 요약됩니다. 스펙 먼저, 코드는 나중. 생각하는 비용을 가장 싼 맨 앞에서 한 번만 치르세요 ― 그러면 AI가 값비싼 재작업 루프로 모호성 세금을 되갚지 않게 됩니다. 다음으로, SDD가 완전한 작업 루프의 어디에 놓이는지 보려면 brainstorm -> plan -> cook -> ship 워크플로를, 그리고 바로 손을 움직이려면 Claude Code로 계획하기(Plan Mode)를 읽어보세요.
Claude Code를 지금 바로 더 강하게 만들고 싶으세요? spec -> plan -> code -> verify 흐름을 조각조각 직접 배선하는 대신 스킬과 서브에이전트에 미리 만들어 넣은 것을 원한다면, Claude Code용 AgentKit(agentkit.best, ak CLI)이 바로 그 흐름을 패키지로 담고 있습니다 ― 환불 보장과 키트 평생 업데이트까지 함께요.