--- name: spec-driven-development description: "코드를 작성하기 전에 스펙을 만듭니다. 새 프로젝트, 기능, 또는 큰 변경을 시작하는데 아직 스펙이 없을 때 사용하세요. 목표와 범위가 있는 PRD나 요구사항 문서를 작성할 때, 또는 요구사항이 불명확하거나 모호하거나 막연한 아이디어로만 있을 때 사용하세요. 요구사항 하나가 독립적으로 테스트할 수 있는 여러 기능에 걸쳐 있어, 스펙을 쓰기 전에 모듈의 기능 맵으로 분해해야 할 때 사용하세요." --- # Spec-Driven Development ## 개요 코드를 쓰기 전에 구조화된 스펙을 작성하세요. 스펙은 여러분과 사람 엔지니어가 함께 쓰는 기준입니다. 무엇을 만드는지, 왜 만드는지, 완료를 어떻게 알 것인지를 정의합니다. 스펙 없는 코드는 추측입니다. ## 언제 사용하나 - 새 프로젝트나 기능을 시작할 때 - 요구사항이 모호하거나 불완전할 때 - 변경이 여러 파일이나 모듈에 닿을 때 - 아키텍처 결정을 내리려 할 때 - 구현에 30분보다 오래 걸릴 작업일 때 **사용하지 않을 때:** 한 줄 수정, 오타 교정, 또는 요구사항이 모호하지 않고 그 자체로 완결된 변경. ## 게이트 워크플로우 스펙 주도 개발에는 네 단계가 있습니다. 그 앞에 범위 점검(단계 0)이 있으며, 요청 하나가 독립적으로 테스트할 수 있는 여러 기능을 묶을 때만 동작합니다. 현재 단계가 검증되기 전에는 다음 단계로 넘어가지 마세요. ``` SPECIFY ──→ PLAN ──→ TASKS ──→ IMPLEMENT │ │ │ │ ▼ ▼ ▼ ▼ Human Human Human Human reviews reviews reviews reviews ``` ### 단계 0: 범위 점검 대부분의 요청은 기능 하나를 설명합니다. 이번 요청이 그렇다면 이 단계를 건너뛰고 바로 스펙 작성(Specify)으로 가세요. 단계 0은 예외를 위한 것이지 일반적인 경우를 위한 것이 아니며, 기능이 하나인 경우에는 계층을 두지 않습니다. **탐지.** 요구사항 하나가 독립적으로 테스트할 수 있는 여러 기능을 묶고 있으면, 스펙을 쓰기 전에 분해하세요. - 요구사항이, 저마다 소비자나 데이터가 다른 기능을 구분해서 말한다 (예: 신원, 결제, 알림, 리포팅) - 인수 기준이, 따로 출시하고 따로 검증할 수 있는 묶음으로 모인다 - 한 기능을 빼거나 바꿔도 나머지 기능의 요구사항을 다시 쓰지 않아도 된다 **스펙을 쓰기 전에 기능 맵을 제안하세요.** 작고 리뷰할 수 있어야 합니다. 프로젝트 계획이 아니라, 모듈 표와 빌드 순서입니다. ```markdown # 기능 맵: [이니셔티브 이름] | 모듈 ID | 책임 | 의존 대상 | |---|---|---| | identity | 계정, 세션, SSO | — | | billing | 플랜, 인보이스, 결제 | identity | | notifications | 이메일과 웹훅 팬아웃 | identity | | reporting | 사용량 대시보드 | billing, notifications | 빌드 순서: identity → billing, notifications → reporting ``` - **안정적인 모듈 ID.** kebab-case로 한 번 정하면, 이니셔티브 도중에 이름을 바꾸지 않습니다. 스펙, 계획, 뒤따르는 명령은 어느 스펙이 활성인지 추측하지 않고 이 ID로 작업을 고릅니다. - **의존 방향만 두고, 순환은 두지 마세요.** 화살표는 한쪽으로만 갑니다. 두 모듈이 서로를 필요로 하면, 그것은 모듈 하나입니다. - **인터페이스는 경계에 둡니다.** 맵은 `billing`이 `identity`에 의존한다고 기록합니다. 둘 사이의 계약은 제공하는 쪽 모듈의 스펙에 둡니다 (설계는 `api-and-interface-design`을 보세요). **맵도 다른 모든 단계와 같이 게이트를 통과합니다.** 모듈 스펙을 하나라도 쓰기 전에, 사용자가 모듈 경계, 의존 방향, 빌드 순서를 리뷰합니다. 맵을 잘못 잡으면 비용이 큽니다. 열 줄을 리뷰하는 비용은 작습니다. **그다음 모듈마다 같은 과정을 반복하세요.** 의존 순서대로 각 모듈에 대해 스펙 작성(Specify) → 계획(Plan) → 작업(Tasks) → 구현(Implement)을 실행하세요. 각 모듈은 그 모듈의 목표, 경계, 성공 기준에 범위를 한정한 자체 스펙을 갖습니다. 승인된 맵은 프로젝트 루트에 저장하고, 각 모듈의 스펙은 그 옆에 모듈 ID로 이름을 붙여 두세요 (`SPEC-identity.md`, `SPEC-billing.md`). 무엇이 있는지의 색인은 파일명을 추측하는 일이 아니라 맵입니다. ### 단계 1: 스펙 작성 (Specify) 높은 수준의 비전에서 시작하세요. 요구사항이 구체적이 될 때까지 사용자에게 명확히 하는 질문을 하세요. **가정을 즉시 드러내세요.** 스펙 내용을 쓰기 전에, 지금 가정하는 것을 나열하세요. ``` 지금 두는 가정: 1. 이것은 웹 애플리케이션이다 (네이티브 모바일이 아니다) 2. 인증은 세션 기반 쿠키를 쓴다 (JWT가 아니다) 3. 데이터베이스는 PostgreSQL이다 (기존 Prisma 스키마를 기준으로) 4. 대상은 최신 브라우저뿐이다 (IE11은 포함하지 않는다) → 지금 고쳐 주세요. 그렇지 않으면 이 가정대로 진행합니다. ``` 모호한 요구사항을 조용히 채우지 마세요. 스펙의 목적은 코드가 작성되기 *전에* 오해를 드러내는 것입니다. 가정은 오해 가운데 가장 위험합니다. **스펙 문서에 다음 여섯 가지 핵심 영역을 담으세요.** 1. **목표:** 무엇을 만들고, 왜 만드는가? 사용자는 누구인가? 성공은 어떤 모습인가? 2. **명령:** 도구 이름만이 아니라, 플래그까지 포함한 실행 가능한 전체 명령. ``` 빌드: npm run build 테스트: npm test -- --coverage 린트: npm run lint -- --fix 개발: npm run dev ``` 3. **프로젝트 구조:** 소스 코드가 어디에 있는지, 테스트는 어디로 가는지, 문서는 어디에 속하는지. ``` src/ → 애플리케이션 소스 코드 src/components → React 컴포넌트 src/lib → 공유 유틸리티 tests/ → 단위 테스트와 통합 테스트 e2e/ → 엔드투엔드 테스트 docs/ → 문서 ``` 4. **코드 스타일:** 스타일을 보여 주는 실제 코드 스니펫 하나가, 스타일을 설명하는 문단 세 개보다 낫습니다. 이름 관례, 포매팅 규칙, 좋은 출력의 예를 포함하세요. 5. **테스트 전략:** 어떤 프레임워크인지, 테스트가 어디에 있는지, 커버리지 기대치, 어떤 관심사에 어떤 테스트 수준을 쓸지. 6. **경계:** 세 갈래로 나눕니다. - **항상 할 일:** 커밋 전에 테스트를 실행하고, 이름 관례를 따르고, 입력을 검증한다 - **먼저 묻기:** 데이터베이스 스키마 변경, 의존성 추가, CI 설정 변경 - **절대 하지 말 것:** 시크릿을 커밋하고, vendor 디렉터리를 수정하고, 승인 없이 실패하는 테스트를 제거한다 **스펙 템플릿:** ```markdown # 스펙: [프로젝트/기능 이름] ## 목표 [무엇을 왜 만드는지. 사용자 스토리 또는 인수 기준.] ## 기술 스택 [프레임워크, 언어, 버전이 있는 주요 의존성] ## 명령 [빌드, 테스트, 린트, 개발. 전체 명령] ## 프로젝트 구조 [설명이 있는 디렉터리 배치] ## 코드 스타일 [예시 스니펫과 핵심 관례] ## 테스트 전략 [프레임워크, 테스트 위치, 커버리지 요구사항, 테스트 수준] ## 경계 - 항상: [...] - 먼저 묻기: [...] - 절대 하지 않음: [...] ## 성공 기준 [완료를 어떻게 알 것인가. 구체적이고 테스트 가능한 조건] ## 미해결 질문 [사람 입력이 필요한, 아직 정하지 못한 것] ``` **외부 스펙 도구:** 이 워크플로우는 형식에 묶이지 않습니다. 프로젝트가 이미 OpenSpec이나 다른 스펙 시스템을 쓰고 있다면, 중복된 `SPEC.md`를 만들지 말고 그 시스템의 아티팩트 형식과 저장 관례를 유지하세요. 이 스킬은 명확화, 내용, 승인 게이트를 담당합니다. 외부 도구는 승인된 스펙을 어떤 형태로 나타낼지를 담당합니다. **지시문을 성공 기준으로 다시 쓰세요.** 막연한 요구사항을 받으면, 구체적인 조건으로 옮기세요. ``` 요구사항: "Make the dashboard faster" (대시보드를 더 빠르게 만들어 달라) 다시 쓴 성공 기준: - 4G 연결에서 대시보드 LCP < 2.5s - 초기 데이터 로드가 500ms 미만에 끝난다 - 로드 중 레이아웃 이동이 없다 (CLS < 0.1) → 이 목표가 맞나요? ``` 이렇게 하면 "더 빠르게"가 무슨 뜻인지 추측하는 대신, 분명한 목표를 향해 반복하고, 다시 시도하고, 문제를 풀 수 있습니다. **스펙을 쓴 뒤 멈추세요 (중요).** 스펙이 저장되면: 1. 스펙을 요약하고 미해결 질문을 나열하세요. 2. 사용자에게 승인하거나 변경을 요청하라고 하세요. 3. **이번 턴을 즉시 종료하세요.** 이 턴에서 단계 2를 시작하거나, `planning-and-task-breakdown`을 호출하거나, 코드를 작성하지 마세요. 계획은 이후 턴에서 사용자가 스펙을 승인한 뒤에만 시작합니다. ### 단계 2: 계획 (Plan) 검증된 스펙으로 기술 구현 계획을 만드세요. 1. 주요 컴포넌트와 그 의존성을 식별하세요 2. 구현 순서를 정하세요 (무엇을 먼저 만들어야 하는지) 3. 위험과 완화 전략을 적으세요 4. 병렬로 만들 수 있는 것과 순차여야 하는 것을 구분하세요 5. 단계 사이의 검증 체크포인트를 정의하세요 > 이 단계들 뒤의 의존성 그래프 매핑과 수직 슬라이스 방법은 `planning-and-task-breakdown`을 따르세요. 그 스킬이 기준 출처입니다. 위의 항목은 가벼운 요약입니다. 서로 어긋나면 `planning-and-task-breakdown`이 우선합니다. > > **출력 관례:** 계획은 `tasks/plan.md`에 저장하고, 작업 목록은 `planning-and-task-breakdown`이 정한 작업 목록 대상에 기록하세요 (기본값 `tasks/todo.md`. 프로젝트는 대신 외부 트래커를 지정할 수 있습니다). `tasks/`가 없으면 만드세요. 뒤따르는 명령(`/build` 등)은 이 기본값을 기대합니다. 계획은 리뷰할 수 있어야 합니다. 사용자가 읽고 "yes, that's the right approach"(맞다, 그 접근이 맞다) 또는 "no, change X"(아니다, X를 바꿔라)라고 말할 수 있어야 합니다. ### 단계 3: 작업 (Tasks) 계획을 구현할 수 있는 개별 작업으로 나누세요. - 각 작업은 집중된 세션 한 번에 끝낼 수 있어야 합니다 - 각 작업에는 명시적인 인수 기준이 있습니다 - 각 작업에는 검증 단계가 있습니다 (테스트, 빌드, 수동 확인) - 작업은 체감되는 중요도가 아니라 의존성 순서로 정렬합니다 - 어떤 작업도 파일을 약 5개보다 많이 바꿔서는 안 됩니다 > 작업 크기 산정과 의존성 순서의 전체 방법은 `planning-and-task-breakdown`을 따르세요. 그 스킬이 기준 출처입니다. 아래 템플릿은 가벼운 인라인 형식입니다. 서로 어긋나면 `planning-and-task-breakdown`이 우선합니다. **작업 템플릿:** ```markdown - [ ] 작업: [설명] - 인수 기준: [끝났을 때 참이어야 하는 것] - 검증: [확인 방법. 테스트 명령, 빌드, 수동 확인] - 파일: [건드릴 파일] ``` ### 단계 4: 구현 (Implement) 작업을 한 번에 하나씩 실행하세요. `skills/incremental-implementation/SKILL.md`(`incremental-implementation`)와 `skills/test-driven-development/SKILL.md`(`test-driven-development`)를 따르세요. 각 단계에서 스펙 전체를 에이전트에 쏟지 말고, `skills/context-engineering/SKILL.md`(`context-engineering`)로 맞는 스펙 섹션과 소스 파일을 불러오세요. ## 스펙을 살아 있게 유지 스펙은 한 번 만들고 끝나는 아티팩트가 아닙니다. 살아있는 문서입니다. - **결정이 바뀌면 업데이트하세요.** 데이터 모델을 바꿔야 한다는 것을 알게 되면, 먼저 스펙을 업데이트한 다음 구현하세요. - **범위가 바뀌면 업데이트하세요.** 추가되거나 빠진 기능은 스펙에 반영되어야 합니다. - **스펙을 커밋하세요.** 스펙은 코드와 함께 버전 관리에 들어갑니다. - **풀 리퀘스트에서 스펙을 참조하세요.** 각 풀 리퀘스트가 구현하는 스펙 섹션으로 링크를 거세요. ## 흔한 합리화 | 합리화 | 현실 | |---|---| | "간단하니 스펙은 필요 없다" | 간단한 작업에 *긴* 스펙은 필요 없습니다. 그래도 인수 기준은 필요합니다. 두 줄짜리 스펙이면 충분합니다. | | "코드를 작성한 뒤에 스펙을 쓰겠다" | 그것은 스펙이 아니라 문서화입니다. 스펙의 가치는 코드 *전에* 명확함을 강제하는 데 있습니다. | | "스펙이 우리를 느리게 할 것이다" | 15분짜리 스펙이 몇 시간의 재작업을 막습니다. 15분의 워터폴이 15시간의 디버깅보다 낫습니다. | | "요구사항은 어차피 바뀐다" | 그래서 스펙은 살아있는 문서입니다. 오래된 스펙도 스펙이 없는 것보다는 낫습니다. | | "사용자는 원하는 것을 알고 있다" | 명확해 보이는 요청에도 숨어 있는 가정이 있습니다. 스펙은 그 가정을 드러냅니다. | | "하나의 큰 기능이라, 나누는 것은 오버헤드다" | 인수 기준이 독립적으로 테스트할 수 있는 묶음으로 모이면, 한 덩어리 스펙은 뒤따르는 모든 작업이 계약 전체를 놓고 생각하게 만듭니다. 열 줄짜리 기능 맵이 비용이 낮은 대안입니다. | | "계획할 때 분해하겠다" | 계획은 스펙 안에서 작업을 나눕니다. 그 시점에는 이미 너무 큰 아티팩트가 있습니다. 모듈 경계와 의존 방향은 스펙을 쓴 다음이 아니라, 쓰기 전에 정해야 합니다. | ## 레드 플래그 - 작성된 요구사항 없이 코드를 쓰기 시작함 - "완료"가 무엇인지 명확히 하기 전에 "그냥 만들기 시작할까요?"라고 물음 - 어떤 스펙이나 작업 목록에도 없는 기능을 구현함 - 아키텍처 결정을 문서화하지 않고 내림 - "무엇을 만들지는 분명하다"는 이유로 스펙을 건너뜀 - 스펙을 쓰고 같은 턴에서 계획이나 코드를 시작함 - 요구사항이 독립적으로 테스트할 수 있는 여러 기능에 걸친 스펙 하나 - 기능 맵이 사전에 승인되지 않아, 구현 중에 모듈 경계나 빌드 순서가 암묵적으로 정해짐 ## 검증 구현으로 넘어가기 전에 다음을 확인하세요. - [ ] 스펙이 여섯 가지 핵심 영역을 모두 다룬다 - [ ] 사용자가 스펙을 리뷰하고 승인했다 - [ ] 스펙을 저장한 뒤 턴이 끝났고, 승인은 이후 턴에서 왔다 - [ ] 성공 기준이 구체적이고 테스트 가능하다 - [ ] 경계(항상 / 먼저 묻기 / 절대 하지 않음)가 정의되어 있다 - [ ] 스펙이 저장소 안의 파일로 저장되어 있다 - [ ] 요청이 독립적으로 테스트할 수 있는 여러 기능을 묶고 있다면, 모듈 스펙을 쓰기 전에 기능 맵(모듈 ID, 의존 방향, 빌드 순서)이 승인되었다 - [ ] 모든 모듈 스펙이 승인된 맵의 모듈 ID로 이어진다