스펙 주도 개발(SDD)은 명세를 코드의 단일 진실 공급원이자 실행 가능한 산출물로 삼아, 아이디어에서 PRD, 구현 계획, 작업, 코드까지를 AI와 템플릿, 헌법으로 자동화·정렬하는 방법론을 제시한다. 핵심 원칙, 워크플로, 명령어(/specify, /plan, /tasks), 품질 게이트와 예시를 통해 변화하는 요구사항 속에서도 일관성과 속도를 유지하는 방식을 설명한다.
수십 년 동안 코드는 왕이었다. 명세는 코드에 복무했다—우리는 코드라는 “진짜 일”을 시작하면 버려질 비계였다. 개발을 안내하기 위해 PRD를 쓰고, 구현을 알리기 위해 설계 문서를 만들고, 아키텍처를 시각화하기 위해 다이어그램을 그렸다. 하지만 이 모든 것은 언제나 코드에 예속되었다. 코드는 진실이었다. 그 외의 것은 기껏해야 좋은 의도였다. 코드는 시간이 흐를수록 유일한 진실의 원천이 되었고, 스펙은 좀처럼 속도를 맞추지 못했다. 자산(코드)과 구현이 하나이기에, 코드를 떠나 병렬 구현을 갖추기는 쉽지 않았다.
스펙 주도 개발(SDD)은 이 권력 구조를 뒤집는다. 명세가 코드에 복무하는 것이 아니라—코드가 명세에 복무한다. PRD(제품 요구사항 문서-명세)는 구현을 위한 가이드가 아니라, 구현을 생성하는 원천이다. 기술 계획은 코딩을 알리는 문서가 아니라, 코드를 생성하는 정밀한 정의다. 이는 소프트웨어를 빌드하는 방식의 점진적 개선이 아니다. 무엇이 개발을 이끄는지에 대한 근본적 재사유다.
명세와 구현 사이의 간극은 소프트웨어 개발의 시작부터 괴롭혀왔다. 우리는 더 나은 문서화, 더 상세한 요구사항, 더 엄격한 프로세스로 다리를 놓으려 했다. 그러나 이 접근들은 간극을 불가피한 것으로 받아들였기에 실패한다. 간극을 줄이려 하지만 결코 없애지 못한다. SDD는 명세와, 그 명세로부터 파생된 구체적 구현 계획을 실행 가능하게 만들어 그 간극을 없앤다. 명세에서 구현 계획으로 이어져 코드가 생성될 때, 간극은 존재하지 않는다—오직 변환만 있을 뿐이다.
이 변환은 이제 AI가 복잡한 명세를 이해하고 구현하며, 상세한 구현 계획을 만들 수 있게 되었기에 가능하다. 하지만 구조 없는 순수한 AI 생성은 혼란을 낳는다. SDD는 엄정하고 완전하며 모호하지 않은 명세와 그에 따른 구현 계획을 통해 작동 가능한 시스템을 생성하는 구조를 제공한다. 명세는 1급 산출물이 되고, 코드는 특정 언어와 프레임워크에서의 그 표현(구현 계획으로부터의 구현)이 된다.
이 새로운 세계에서 소프트웨어 유지보수는 명세의 진화와 동의어가 된다. 개발팀의 의도는 자연어(의도 주도 개발), 디자인 자산, 핵심 원칙 및 기타 가이드라인으로 표현된다. 개발의 공용어는 더 높은 추상화 수준으로 이동하고, 코드는 라스트 마일 접근이 된다.
디버깅은 잘못된 코드를 생성하는 명세와 구현 계획을 고치는 일이다. 리팩터링은 명료성을 위해 재구조화하는 일이다. 전체 개발 워크플로는 명세를 단일 진실의 원천으로 재편되고, 구현 계획과 코드는 지속적으로 재생성되는 출력물이 된다. 앱을 새 기능으로 업데이트하거나 우리가 창의적 존재이기에 새로운 병렬 구현을 만들 때는, 명세를 재검토하고 새로운 구현 계획을 만든다. 이 과정은 0 -> 1, (1', ..), 2, 3, N이다.
개발팀은 창의성, 실험, 비판적 사고에 집중한다.
워크플로는 종종 모호하고 불완전한 아이디어에서 시작한다. AI와의 반복적 대화를 통해 이 아이디어는 포괄적인 PRD로 진화한다. AI는 명확화 질문을 던지고, 엣지 케이스를 식별하며, 정밀한 수용 기준을 정의하는 데 도움을 준다. 전통적 개발에서 며칠간 회의와 문서화가 필요했던 일이, 집중된 명세 작업 몇 시간으로 끝난다. 이는 전통적 SDLC를 변형한다—요구사항과 설계가 분리된 단계가 아니라 지속적 활동이 된다. 이는 팀 프로세스를 지지한다. 팀 리뷰를 거친 명세는 브랜치에서 작성·버전 관리되고, 병합된다.
제품 관리자가 수용 기준을 업데이트하면, 구현 계획은 영향을 받는 기술적 결정을 자동으로 표시한다. 아키텍트가 더 나은 패턴을 발견하면, PRD는 새로운 가능성을 반영하도록 업데이트된다.
이 명세 과정 전반에서 리서치 에이전트가 중요한 컨텍스트를 수집한다. 라이브러리 호환성, 성능 벤치마크, 보안 함의를 조사한다. 조직 제약은 자동으로 발견되고 적용된다—회사의 데이터베이스 표준, 인증 요구사항, 배포 정책이 모든 명세에 매끄럽게 통합된다.
PRD로부터 AI는 요구사항을 기술적 결정으로 매핑하는 구현 계획을 생성한다. 모든 기술 선택에는 근거가 문서화된다. 모든 아키텍처 결정은 특정 요구사항으로 추적된다. 이 과정 전반에서 일관성 검증이 지속적으로 품질을 개선한다. AI는 명세의 모호성, 모순, 빈틈을 일회성 게이트가 아니라 지속적 정제 과정으로 분석한다.
코드 생성은 명세와 구현 계획이 충분히 안정되는 즉시 시작되지만, “완전할” 필요는 없다. 초기 생성물은 탐색적일 수 있다—명세가 실제로도 말이 되는지 시험한다. 도메인 개념은 데이터 모델이 된다. 사용자 스토리는 API 엔드포인트가 된다. 수용 시나리오는 테스트가 된다. 이는 명세를 통해 개발과 테스트를 융합한다—테스트 시나리오는 코드 이후에 작성되는 것이 아니라, 구현과 테스트를 모두 생성하는 명세의 일부다.
피드백 루프는 초기 개발을 넘어 확장된다. 프로덕션 메트릭과 인시던트는 핫픽스만 유발하는 것이 아니라—다음 재생성을 위한 명세 업데이트를 유도한다. 성능 병목은 새로운 비기능 요구사항이 된다. 보안 취약점은 향후 모든 생성물에 영향을 미치는 제약이 된다. 명세, 구현, 운영 현실 사이의 이 반복적 춤에서 진정한 이해가 싹트고, 전통적 SDLC는 지속적 진화로 변모한다.
세 가지 트렌드가 SDD를 가능할 뿐 아니라 필수로 만든다:
첫째, AI 역량은 자연어 명세로부터 신뢰할 수 있는 동작 코드를 생성할 수 있는 임계점을 넘었다. 이는 개발자를 대체하려는 것이 아니다—명세에서 구현으로의 기계적 번역을 자동화하여 개발자의 효과성을 증폭시키려는 것이다. 탐색과 창의성을 확대하고, “처음부터 다시”를 손쉽게 지원하며, 더하기·빼기와 비판적 사고를 도와준다.
둘째, 소프트웨어 복잡도는 기하급수적으로 증가하고 있다. 현대 시스템은 수십 개의 서비스, 프레임워크, 의존성을 통합한다. 이러한 모든 조각을 수동 프로세스로 원래 의도와 정렬된 상태로 유지하는 것은 갈수록 어려워진다. SDD는 명세 기반 생성으로 체계적 정렬을 제공한다. 프레임워크는 인간 우선이 아닌 AI 우선 지원을 제공하도록 진화하거나, 재사용 가능한 컴포넌트를 중심으로 아키텍처를 구성할 수 있다.
셋째, 변화의 속도가 가속한다. 요구사항은 그 어느 때보다 빠르게 변한다. 피벗은 예외가 아니라—기대치다. 현대 제품 개발은 사용자 피드백, 시장 상황, 경쟁 압력에 기반한 신속한 반복을 요구한다. 전통적 개발은 이러한 변화를 방해 요소로 취급한다. 각 피벗은 문서, 설계, 코드를 수동으로 일일이 변경·전파해야 한다. 그 결과는 속도를 제한하는 느리고 신중한 업데이트이거나, 기술부채를 쌓는 빠르고 무모한 변경이다.
SDD는 가정/시뮬레이션 실험을 지원할 수 있다. “더 많은 티셔츠를 판매하기 위한 비즈니스 니즈를 위해 애플리케이션을 재구현하거나 변경해야 한다면, 어떻게 구현하고 실험할 것인가?”
SDD는 요구사항 변경을 장애물이 아닌 정상적 워크플로로 변환한다. 명세가 구현을 이끌면, 피벗은 수동 재작성 대신 체계적 재생성이 된다. PRD의 핵심 요구사항을 바꾸면, 영향을 받는 구현 계획이 자동으로 업데이트된다. 사용자 스토리를 수정하면, 대응하는 API 엔드포인트가 재생성된다. 이는 초기 개발만을 위한 것이 아니다—불가피한 변화 속에서 엔지니어링 속도를 유지하는 일이다.
공용어로서의 명세: 명세가 주 산출물이 된다. 코드는 특정 언어와 프레임워크에서의 표현이 된다. 소프트웨어 유지보수는 명세를 진화시키는 일이다.
실행 가능한 명세: 명세는 동작하는 시스템을 생성할 만큼 정밀하고, 완전하며, 모호하지 않아야 한다. 이는 의도와 구현 사이의 간극을 제거한다.
지속적 정제: 일관성 검증은 일회성 게이트가 아니라 지속적으로 일어난다. AI가 명세의 모호성, 모순, 빈틈을 계속 분석한다.
리서치 기반 컨텍스트: 리서치 에이전트가 기술 옵션, 성능 영향, 조직 제약을 조사하며 명세 과정 전반에 걸쳐 중요한 컨텍스트를 모은다.
양방향 피드백: 프로덕션 현실이 명세의 진화를 이끈다. 메트릭, 인시던트, 운영에서의 학습이 명세 정제의 입력이 된다.
탐색을 위한 분기: 동일한 명세에서 성능, 유지보수성, 사용자 경험, 비용 등 상이한 최적화 목표를 탐색하기 위해 다중 구현 접근을 생성한다.
오늘날 SDD를 실천하려면 기존 도구를 조합하고, 프로세스 전반에 걸쳐 규율을 유지해야 한다. 이 방법론은 다음으로 실천할 수 있다:
핵심은 명세를 진실의 원천으로 대하고, 코드를 그 명세를 섬기는 생성물로 취급하는 것이다—거꾸로가 아니다.
SDD 방법론은 스펙 → 계획 → 태스크화 워크플로를 자동화하는 세 가지 강력한 명령으로 크게 강화된다:
이 명령은 단순한 기능 설명(사용자 프롬프트)을 자동 저장소 관리와 함께 완전하고 구조화된 명세로 변환한다:
specs/[branch-name]/ 구조 생성기능 명세가 존재하면, 이 명령은 포괄적인 구현 계획을 생성한다:
계획이 생성된 후, 이 명령은 계획과 관련 설계 문서를 분석하여 실행 가능한 작업 목록을 생성한다:
plan.md(필수) 그리고 존재한다면 data-model.md, contracts/, research.md 읽기[P] 표시하고 안전한 병렬 그룹 윤곽 제시tasks.md 작성—태스크 에이전트가 즉시 실행 가능이 명령들이 전통적 개발 워크플로를 어떻게 변환하는지 보자:
전통적 접근:
1. 문서에 PRD 작성 (2-3시간)
2. 설계 문서 작성 (2-3시간)
3. 프로젝트 구조 수동 셋업 (30분)
4. 기술 명세 작성 (3-4시간)
5. 테스트 계획 수립 (2시간)
합계: 문서 작업 약 12시간
명령을 활용한 SDD 접근:
/specify 메시지 히스토리와 사용자 프레즌스가 있는 실시간 채팅 시스템
/plan 실시간 메시징은 WebSocket, 히스토리는 PostgreSQL, 프레즌스는 Redis 사용
/tasks
15분 만에 다음을 갖춘다:
이 명령들은 시간을 절약할 뿐 아니라—일관성과 완전성을 강제한다:
이 명령들은 명세를 정적 문서가 아닌 실행 가능한 산출물로 다루는 SDD 원칙을 구현한다. 명세 과정을 불가피한 악이 아닌 개발을 이끄는 추진력으로 전환한다.
이 명령들의 진정한 힘은 자동화 자체가 아니라, 템플릿이 LLM의 행동을 더 높은 품질의 명세로 유도하는 방식에 있다. 템플릿은 LLM의 출력을 생산적으로 제약하는 정교한 프롬프트로 작동한다:
- ✅ 사용자가 무엇을 필요로 하고 왜 필요한지(WHAT/WHY)에 집중
- ❌ 어떻게 구현할지(HOW)는 피함 (기술 스택, API, 코드 구조 금지)
이 제약은 LLM이 올바른 추상화 수준을 유지하도록 강제한다. LLM이 자연스럽게 “React와 Redux로 구현”으로 뛰어들려 할 때, 템플릿은 “사용자가 자신의 데이터에 대한 실시간 업데이트를 원한다”에 집중하게 만든다. 이 분리는 구현 기술이 바뀌어도 명세가 안정적으로 유지되도록 보장한다.
두 템플릿 모두 [NEEDS CLARIFICATION] 마커 사용을 의무화한다:
사용자 프롬프트로 스펙을 생성할 때:
1. 모든 모호성을 표시: [NEEDS CLARIFICATION: 구체적 질문] 사용
2. 추측 금지: 프롬프트에 명시되지 않은 것은 표시만 할 것
이는 그럴듯하지만 잘못된 가정을 하는 LLM의 흔한 행태를 방지한다. 예를 들어 “로그인 시스템”이 이메일/비밀번호 인증을 쓴다고 추측하는 대신, LLM은 반드시 [NEEDS CLARIFICATION: 인증 방식 미정 - 이메일/비밀번호, SSO, OAuth?]로 표시해야 한다.
템플릿에는 명세의 “단위 테스트” 역할을 하는 포괄적 체크리스트가 포함된다:
이 체크리스트는 LLM이 산출물을 체계적으로 자체 검토하도록 강제해, 놓칠 수 있는 빈틈을 잡아낸다. 일종의 품질 보증 프레임워크다.
구현 계획 템플릿은 단계별 게이트로 아키텍처 원칙을 강제한다:
이 게이트들은 과도한 엔지니어링을 방지하기 위해 LLM이 모든 복잡성을 명시적으로 정당화하도록 만든다. 게이트에 실패하면 LLM은 “복잡도 추적” 섹션에 이유를 문서화해야 하며, 이는 아키텍처 결정에 대한 책무성을 만든다.
중요: 이 구현 계획은 고수준이고 가독성을 유지해야 한다.
코드 샘플, 상세 알고리즘, 방대한 기술 명세는
반드시 `implementation-details/`의 적절한 파일에 배치할 것
이는 명세가 읽기 힘든 코드 덤프로 변해버리는 흔한 문제를 방지한다. LLM은 주 문서는 내비게이션이 용이하도록 유지하면서, 복잡한 세부는 별도 파일로 추출하는 법을 학습한다.
### 파일 생성 순서
1. API 명세가 담긴 `contracts/`를 먼저 생성
2. 테스트 파일을 다음 순서로 생성: 계약 → 통합 → e2e → 단위
3. 테스트를 통과시키기 위해 소스 파일 생성
이 순서 제약은 LLM이 구현에 앞서 테스트 가능성과 계약을 먼저 생각하도록 만들어, 더 견고하고 검증 가능한 명세로 이어진다.
- [ ] 추측성 또는 “있으면 좋음” 기능 금지
- [ ] 모든 페이즈에 명확한 전제조건과 산출물이 있음
이는 LLM이 구현을 복잡하게 만드는 “있으면 좋을” 기능을 추가하는 것을 막는다. 모든 기능은 명확한 수용 기준을 가진 구체적 사용자 스토리로 소급되어야 한다.
이 제약들은 함께 작동하여 다음과 같은 명세를 만든다:
템플릿은 LLM을 창작자에서 훈련된 명세 엔지니어로 바꾸어, 일관되게 고품질의 실행 가능한 명세를 생산하도록 그 역량을 통제된 방향으로 유도한다.
SDD의 중심에는 헌법이 있다—명세가 코드가 되는 방식을 지배하는 불변의 원칙 집합이다. 헌법(memory/constitution.md)은 시스템의 아키텍처 DNA로서 작동하여, 생성되는 모든 구현이 일관성, 단순성, 품질을 유지하게 한다.
헌법은 개발 프로세스의 모든 측면을 형성하는 아홉 개의 조항을 정의한다:
모든 기능은 예외 없이 독립형 라이브러리로 시작해야 한다. 이는 시작부터 모듈식 설계를 강제한다:
Specify의 모든 기능은 반드시(MUST) 독립형 라이브러리로서 존재를 시작해야 한다.
먼저 재사용 가능한 라이브러리 컴포넌트로 추상화하지 않고서는
어떠한 기능도 애플리케이션 코드에 직접 구현해서는 안 된다.
이 원칙은 명세가 단일체(monolith)가 아닌 모듈식이고 재사용 가능한 코드를 생성하도록 보장한다. LLM이 구현 계획을 생성할 때, 기능을 경계가 명확하고 의존성이 최소인 라이브러리로 구조화해야 한다.
모든 라이브러리는 명령줄 인터페이스를 통해 기능을 노출해야 한다:
모든 CLI 인터페이스는 반드시:
- 텍스트 입력을 수용(표준 입력, 인자, 파일)
- 텍스트 출력을 생성(표준 출력)
- 구조화된 데이터 교환을 위해 JSON 형식을 지원
이는 가시성과 테스트 가능성을 강제한다. LLM은 불투명한 클래스 안에 기능을 숨길 수 없다—모든 것이 텍스트 기반 인터페이스를 통해 접근되고 검증 가능해야 한다.
이는 협상 불가다: 모든 구현은 엄격한 TDD(테스트 주도 개발)를 따라야 한다.
다음이 완료되기 전에는 어떤 구현 코드도 작성되어서는 안 된다:
1. 단위 테스트 작성
2. 테스트가 사용자에게 검토·승인됨
3. 테스트가 실패(Red 단계)함이 확인됨
이는 전통적 AI 코드 생성의 상을 완전히 뒤집는다. “코드를 생성하고 잘 작동하길 바라는” 대신, LLM은 먼저 행동을 정의하는 포괄적 테스트를 생성하고 승인을 받은 뒤에만 구현을 생성해야 한다.
섹션 7.3: 최소 프로젝트 구조
- 초기 구현에서는 최대 3개 프로젝트
- 추가 프로젝트는 문서화된 정당성이 필요
섹션 8.1: 프레임워크 신뢰
- 프레임워크를 감싸지 말고 그 기능을 직접 사용할 것
LLM이 자연스럽게 정교한 추상화를 만들려 할 때, 이 조항들은 모든 복잡성의 층을 정당화하도록 강제한다. 구현 계획 템플릿의 “페이즈 -1 게이트”가 이러한 원칙을 직접적으로 집행한다.
격리된 단위 테스트보다 현실 세계 테스트를 우선시한다:
테스트는 반드시 현실적인 환경을 사용해야 한다:
- 모의 객체(mock)보다 실제 데이터베이스 선호
- 스텁보다 실제 서비스 인스턴스 사용
- 구현 전에 계약 테스트 의무화
이는 생성된 코드가 이론이 아니라 실제로 작동하도록 보장한다.
구현 계획 템플릿은 구체적 체크포인트로 이 조항들을 운영화한다:
이 게이트들은 아키텍처 원칙을 위한 컴파일 타임 검사처럼 작동한다. LLM은 게이트를 통과하지 못하면 “복잡도 추적” 섹션에 정당한 예외를 문서화하지 않고는 진행할 수 없다.
헌법의 힘은 그 불변성에 있다. 구현 세부는 진화할 수 있지만, 핵심 원칙은 변하지 않는다. 이는 다음을 제공한다:
섹션 4.2: 개정 절차
이 헌법의 수정은 다음을 요구한다:
- 변경에 대한 명시적 근거 문서화
- 프로젝트 관리자들의 검토 및 승인
- 하위 호환성 평가
이는 방법론이 안정성을 유지하면서도 학습하고 개선되도록 허용한다. 헌법은 날짜가 있는 개정을 통해 스스로의 진화를 보여주며, 현실 세계의 경험을 바탕으로 원칙이 어떻게 정제될 수 있는지를 시연한다.
헌법은 단지 규칙집이 아니다—LLM이 코드 생성을 사고하는 방식을 형성하는 철학이다:
이 원칙을 명세와 계획 과정에 내장함으로써, SDD는 생성된 코드가 단지 기능하는 것을 넘어—유지보수 가능하고, 테스트 가능하며, 아키텍처적으로 건전하도록 보장한다. 헌법은 AI를 단순한 코드 생성기가 아닌, 시스템 설계 원칙을 존중하고 강화하는 아키텍처 파트너로 바꾼다.
이는 개발자를 대체하거나 창의성을 자동화하는 문제가 아니다. 기계적 번역을 자동화해 인간의 역량을 증폭하는 일이다. 명세, 리서치, 코드가 함께 진화하는 촘촘한 피드백 루프를 만드는 일이며, 각 반복은 의도와 구현 사이의 정렬을 더 깊이 있게 만든다.
소프트웨어 개발에는 의도와 구현 사이의 정렬을 유지하는 더 나은 도구가 필요하다. SDD는 코드를 “안내”하는 데 그치지 않고 코드를 “생성”하는 실행 가능한 명세를 통해 이 정렬을 달성하는 방법론을 제공한다.