들어가며 — 병목은 코드가 아니라 “무엇을 만들지”였다
AI로 게임을 만드는 시리즈를 진행하면서 가장 크게 체감한 게 하나 있다.
속도의 병목은 코드 작성이 아니라 의사결정이다.
뱀서라이크 4일차에 GDD(Game Design Document)를 확정하고, 그 뒤로는 손대지 않기로 했다. 36개 피처의 수치와 동작을 전부 못 박았다. 그리고 5일차, 그 36개 중 31개를 하루 만에 구현해 86% 완성에 도달했다. 코드를 빨리 쳐서가 아니다. “무엇을 만들지” 고민이 사라지니 AI가 정확하게 채운 것이다.
반대 경우도 겪었다. 스펙 없이 “뱀서라이크 만들어줘”라고 던지면 AI는 제네릭한 템플릿을 뱉고, 그걸 내 게임으로 고치는 데 더 많은 시간이 든다. 명확한 스펙을 주면 AI는 정확하게 구현하고, 모호한 지시를 주면 AI는 모호하게 구현한다.
이 경험에는 이름이 있었다. 스펙 주도 개발(Spec-Driven Development, SDD) 이다. 이 글은 SDD가 무엇인지를 내가 직접 겪은 것으로 풀고, 함께 묶여서 헷갈리기 쉬운 TDD·BDD·DDD와 어떻게 다르고 어떻게 같이 쓰는지를 정리한다. (앞선 시리즈를 안 읽었어도 괜찮다 — 여기선 그 경험을 방법론으로만 뽑아 쓴다.)
SDD란 무엇인가 — 코드가 아니라 스펙이 단일 원천
SDD의 핵심 명제는 한 줄이다.
코드가 아니라 스펙이 단일 원천(single source of truth)이다.
전통적으로 스펙은 코드를 쓰기 위한 발판이고, 일단 코드가 나오면 버려지거나 낡는다. SDD는 이걸 뒤집는다. 스펙을 먼저 정밀하게 쓰고, 그 스펙으로부터 구현을 생성하며, 바꿀 게 생기면 코드가 아니라 스펙을 고친 뒤 다시 생성한다. 코드는 재생성 가능한 산출물이고, 영속하는 1급 자산은 스펙이다.
이 흐름을 도구로 만든 게 GitHub Spec Kit 같은 것들이다. 단계는 이렇다.
constitution → /specify → /plan → /tasks → /implement
(불가침 원칙) (무엇을) (어떻게) (잘게 쪼갬) (AI가 구현)
- constitution: 프로젝트의 협상 불가 원칙. “테스트는 항상 먼저”, “CLI 우선” 같은 규칙을 코드 이전에 박아 둔다.
- specify: 무엇을 왜 만드는지(요구사항). 어떻게는 아직 안 적는다.
- plan: 기술 스택과 아키텍처.
- tasks: 구현 가능한 단위로 분해.
- implement: AI 에이전트가 위 문서들을 레일 삼아 코드를 생성.
여기서 멈칫했다. 이거, 내가 이미 하던 거다. 도구 이름을 몰랐을 뿐이다.
카타나 제로 스타일 게임을 만들 때, 리포지토리에 둔 CLAUDE.md(에이전트 룰북)가 사실상 constitution이었다. 블로그 본문엔 안 실었지만 프로젝트 파일로 존재한다 — 일부를 옮기면 이렇다.
### Rule 1 — Object Instantiation
Instantiate() is FORBIDDEN everywhere except inside PoolManager pool factory callbacks.
### Rule 2 — Canonical Spec
Assets/_Project/GDD.md is the single source of truth.
GDD.md가 specify/plan에 해당하는 스펙이고, CLAUDE.md의 HARD RULES가 constitution이다. AI 에이전트는 매 작업마다 이 두 문서를 참조해 같은 기준으로 코드를 생성했다. Spec Kit이 “context를 파일로 만들어 버전 관리한다”고 말하는 게 정확히 이거다.
내가 직접 겪은 SDD — “스펙이 확정되면 속도가 폭발한다”
일반론으로 끝내면 재미없으니, 실제로 부딪힌 것들을 정리한다.
① 스펙의 구체성이 결과의 품질을 결정한다. 뱀서라이크 GDD에는 무기 20종의 데미지·쿨다운·레벨별 수치, 적 5종의 HP·이동속도·스폰 패턴이 수치까지 전부 확정돼 있었다. 그래서 AI에게 “M1-5 구현해”라고만 해도 입력 방식, 이동 속도, 정규화 규칙까지 알고 코드를 만들었다. 스펙이 구체적인 만큼 결과가 정확했다.
② 스펙은 코드 0줄일 때 가장 비싸고, 가장 값지다. 10일차에 GDD 900줄, CLAUDE.md 342줄, asmdef 13개를 만들고 코드는 0줄이었다. 하루를 통째로 문서에 썼다. 그 투자가 11일차에 회수됐다 — 스크립트 44개, 테스트 87개, 순환 의존성 0, 싱글톤 0. 스펙에 수치가 확정돼 있으니 “이 값 얼마로 하지?”라는 고민이 없고, constitution에 컨벤션이 박혀 있으니 AI가 일관된 코드를 뽑았다.
③ 스펙은 살아 있고, 진화한다. 같은 게임의 첫 스펙 문서는 GAME_SPEC.md였는데, 문서 머리에 이렇게 적혀 있었다 — “Spec-Driven Development Document”. 그런데 개발이 진행되며 이 문서는 통째로 폐기(superseded)되고 GDD.md가 새 단일 원천이 됐다. 스펙은 돌에 새긴 게 아니라, 가장 먼저 고치는 살아 있는 문서다.
요약하면, “무엇을 만들지”를 문서로 고정하는 순간 의사결정 병목이 사라지고, 그 자리에서 속도가 터진다. 이게 내가 SDD에서 본 실체다.
스펙은 법이 아니라 출발점이다 — SDD의 함정
SDD를 오해하면 워터폴로 돌아간다. “스펙을 완벽하게 다 쓴 다음 구현”은 함정이다. 두 가지를 짚어야 한다.
스펙 수치는 출발점이지 정답이 아니다. 패링 시스템을 만들 때 GDD에는 판정 윈도우를 ±50/100/200ms로 설계했다. 그런데 구현 후 직접 플레이해 보니 너무 빡빡했다. 패링은 BGM 비트가 아니라 적 공격 도달이라는 반응형 이벤트가 기준이라 반응 시간이 더 필요했다. 그래서 ≤80/150/250ms로 넓혔다. GDD 수치는 출발점이고, 실제 체감은 구현 후 조율해야 한다.
과하게 명세하면 워터폴, 안 하면 vibe coding. SDD는 그 둘 사이다. 핵심은 전부 적는 게 아니라 맞는 것을 적는 것이다 — 수치, 엣지 케이스, 경계 조건처럼 AI가 추측하면 틀리는 것들. 가령 “패링 스팸 어떻게 막지?”를 기획 단계에서 “실패 시 0.3초 경직”으로 정해 두면, 구현할 때 그 고민이 통째로 사라진다. 반대로 카메라 연출 디테일 같은 건 만들어 보고 조율하는 게 빠르다.
TDD · SDD · BDD · DDD — 경쟁이 아니라 다른 질문에 답한다
여기서 본론. 이 네 가지는 자주 한 묶음으로 거론되는데, 서로 경쟁하는 대체재가 아니다. 각자 다른 질문에 답하고, 범위(scope)가 다르다.
| 방법론 | 답하는 질문 | 산출물 | 범위 | 기원 |
|---|---|---|---|---|
| TDD | 이게 진짜 동작하나? | 실패하는 테스트 → 통과 → 리팩터 | 코드 단위 | Kent Beck |
| BDD | 사용자가 기대하는 행동은? | Given-When-Then 시나리오 | 기능/행동 | Dan North |
| DDD | 이 도메인을 어떻게 모델링하나? | 유비쿼터스 언어, 바운디드 컨텍스트 | 구조/모델 | Eric Evans |
| SDD | 정확히 무엇을, 왜 만드나? | 실행 가능한 스펙(constitution/spec/plan/tasks) | 기능~아키텍처 | 2025, AI 코딩 시대 |
핵심은 범위와 시점이다. 네 개를 한 축에 세우면 이렇게 읽힌다.
TDD는 SDD의 단위(unit) 버전이다. 테스트를 먼저 쓰는 건 사실 “이 함수는 이렇게 동작해야 한다”는 마이크로 스펙을 먼저 쓰는 것이다. 리듬 게임의 판정기 BeatJudge를 만들 때 50ms 경계에서 Perfect→Great 전환이 정확히 일어나는지 경계값 테스트를 먼저 깔았다. SDD는 이 “먼저 명세한다”는 규율을 함수가 아니라 기능·시스템·아키텍처 수준으로 끌어올린 것이다.
BDD는 SDD의 가장 직접적인 조상이다. BDD는 “행동을 먼저, 비즈니스 언어로” 쓴다. Gherkin 시나리오가 곧 실행 가능한 명세다. 위 패링 스펙을 BDD로 적으면 이렇게 된다.
Scenario: 퍼펙트 패링
Given 적이 공격을 텔레그래프하고
When 플레이어가 도달 80ms 이내에 패링하면
Then 반격 대미지 200%와 리듬 게이지 +15를 받는다
이건 기획서 한 줄이면서 동시에 테스트 케이스다. SDD의 spec은 이 행동 명세를 시스템 전체로 확장한 형태다.
DDD는 유비쿼터스 언어로 SDD와 만난다. DDD의 핵심은 도메인 용어를 개발자·이해관계자·코드가 똑같이 쓰는 것(ubiquitous language)과, 모듈 경계를 도메인으로 가르는 것(bounded context)이다. 내 프로젝트에서 asmdef로 Player/Enemy/Combat을 갈라 ICombatTarget 인터페이스로만 소통하게 한 게 바운디드 컨텍스트의 약한 버전이고, GDD/CLAUDE.md가 공유하는 용어들이 유비쿼터스 언어다. AI 시대엔 그 언어를 읽는 사람이 한 명 더 늘었다 — AI 에이전트도 같은 도메인 언어를 읽어야 같은 걸 가리킨다. 그래서 DDD가 깐 “공통 언어” 토대 위에 SDD의 스펙이 얹힌다.
정리하면, 넷은 한 줄에서 충돌하지 않고 층으로 쌓인다.
SDD가 무엇을·왜를, BDD가 시스템 전반의 행동을, TDD가 코드 단위의 정확성을 맡는다. DDD는 그 셋이 공유할 언어와 경계를 깐다.
실제로 내 전투 프로토타입이 이 합성이었다. GDD(SDD)로 무엇을 만들지 정하고, 패링 등급 윈도우(BDD스러운 행동 명세)를 정하고, BeatJudge 경계값 테스트(TDD)로 정확성을 잠갔다. 셋 중 하나만 했다면 어딘가 구멍이 났을 것이다.
AI 시대에 왜 SDD가 부활했나
SDD의 아이디어 자체(“먼저 명세하라”)는 새것이 아니다. 워터폴의 명세서, BDD의 시나리오, DDD의 도메인 모델이 전부 그 갈래다. 그런데 2025년 들어 SDD라는 이름으로 다시 떠오른 이유는 하나다 — AI 코딩 에이전트.
이른바 “vibe coding”의 실패 모드 때문이다. LLM에게 막연히 시키면 그럴듯한데 의도와 어긋나는 코드가 나온다. 존재하지 않는 API를 환각하고, 명시되지 않은 가정을 수십 개 깔고, 프로젝트가 커질수록 의도에서 점점 멀어진다. AI는 패턴 완성엔 탁월하지만 독심술은 못한다. 스펙은 정확히 그 독심술의 빈자리를 메우는 장치다.
그래서 AI 시대의 SDD는 두 가지가 핵심이 된다.
- 스펙이 버전 관리되는 1급 산출물이 된다. 코드는 언제든 재생성할 수 있고, 영속하는 건 스펙이다. 리뷰·수정·되돌리기를 코드가 아니라 스펙에서 한다.
- constitution이 모든 AI 상호작용에 같은 레일을 깐다.
CLAUDE.md든constitution.md든, 한 번 박아 둔 원칙이 매 호출마다 동일하게 적용돼 결과가 일관된다.
도구는 GitHub Spec Kit, AWS Kiro처럼 빠르게 늘고 있다. 하지만 핵심은 도구가 아니라 습관이다. 나는 Spec Kit이라는 이름을 알기 한참 전부터 GDD + CLAUDE.md로 SDD를 하고 있었다. 도구는 이 습관을 정형화해 줄 뿐이다.
마치며
SDD는 혁명적인 신기술이 아니다. 명세 기반 개발의 오래된 아이디어가, AI가 구현을 떠맡으면서 “무엇을 만들지 정하는 일”이 다시 1급 작업으로 올라온 결과다.
- TDD/BDD/DDD/SDD는 경쟁하지 않는다. 답하는 질문이 다르다. 지금 내가 답하려는 질문이 “동작하나(TDD)”인지, “기대 행동이 뭔가(BDD)”인지, “도메인을 어떻게 가르나(DDD)”인지, “무엇을 왜 만드나(SDD)”인지를 먼저 정하면 도구 선택은 따라온다.
- AI 시대엔 스펙이 코드보다 오래 산다. 코드는 재생성되고, 스펙이 남는다.
이 시리즈를 시작한 이래 가장 비싸게 배운 교훈을 다시 적으면, 속도의 병목은 코드 작성이 아니라 의사결정이다. SDD는 그 의사결정을 문서로 고정해 한 번만 내리게 하는 규율이다. 그리고 그 문서를, 이제는 사람만이 아니라 AI도 같이 읽는다.
AI가 코드를 쓰는 시대에 사람이 쥐고 있어야 할 건 코드가 아니라 스펙이다 — 무엇을 왜 만드는지만 정확하면, 나머지는 생성된다.
댓글