본문 바로가기
AI Native/GitHub Spec Kit으로 구현하는 SDD v2

d01/06. specify-workshop.md

by Toddler_AD 2026. 5. 2.

1일차 4교시: Specify 작성 워크숍

이 교시는 무엇을 만들 것인가와 왜 필요한가를 문서화하는 시간입니다. 설계서 기준으로 /speckit.specify는 constitution을 참조하여 spec을 만들고, 모호한 항목에는 [NEEDS CLARIFICATION]를 남깁니다.

교시 목표

  • /speckit.specify에 넣어야 할 내용을 설명할 수 있다.
  • constitution과 specify의 차이를 말할 수 있다.
  • specify와 plan의 차이를 말할 수 있다.
  • 좋은 기능 설명과 나쁜 기능 설명을 구분할 수 있다.

/speckit.specify의 역할

specify는 사용자 관점의 요구사항 문서를 만드는 단계입니다.

여기에는 보통 다음이 들어갑니다.

  • 누가 쓰는가
  • 어떤 문제를 해결하는가
  • 사용자가 어떤 행동을 할 수 있어야 하는가
  • 어떤 규칙과 제약이 있는가
  • 성공을 어떻게 확인할 것인가

/speckit.constitution과 무엇이 다른가

  • constitution은 프로젝트 전체의 원칙
  • specify는 이번 기능의 요구사항

예를 들어 테스트 없는 기능은 완료로 보지 않는다는 constitution입니다.

반면 사용자는 태그를 추가, 삭제, 필터링할 수 있어야 한다는 specify입니다.

/speckit.plan과 무엇이 다른가

  • specify는 무엇을 왜
  • plan은 어떻게

예를 들어 태그는 한 Todo에 중복으로 붙을 수 없다는 specify입니다.

반면 TodoTag 조인 테이블을 두고 SQLite UNIQUE 제약을 건다는 plan입니다.

좋은 입력의 구조

아래 요소를 넣으면 초심자도 비교적 안정적으로 spec을 만들 수 있습니다.

  1. 사용자 또는 역할
  2. 해결하려는 문제
  3. 핵심 시나리오
  4. 비즈니스 규칙
  5. 수용 기준 힌트

다양한 입력 예시

예시 1: Todo 태그 기능

사용자가 Todo 항목에 태그를 붙여 분류할 수 있는 기능을 정의해줘.

- 대상 사용자: 개인 사용자
- 목적: 할 일을 맥락별로 분류하고 빠르게 찾기 위해
- 핵심 행동: 태그 추가, 태그 제거, 태그별 필터링, 태그 목록 보기
- 규칙: 같은 태그를 한 항목에 중복으로 붙일 수 없다
- 규칙: 태그 이름은 20자 이하
- 기대 결과: 태그를 사용해 Todo를 보기 쉽게 분류할 수 있어야 한다

예시 2: 사진 앨범 정리 앱

사용자가 사진을 앨범으로 정리할 수 있는 앱의 기능 명세를 작성해줘.

- 대상 사용자: 개인 사용자
- 목적: 많은 사진을 날짜와 주제별로 정리하기 위해
- 핵심 행동: 앨범 생성, 앨범 이름 변경, 사진 이동, 앨범 정렬 변경
- 규칙: 앨범 안에 다른 앨범을 넣을 수 없다
- 규칙: 사진은 업로드 시 원본 촬영일을 유지해야 한다
- 기대 결과: 사용자가 여러 장의 사진을 빠르게 찾아볼 수 있어야 한다

예시 3: 교육용 과제 제출 기능

학생이 과제를 제출하고 제출 이력을 확인할 수 있는 기능 명세를 작성해줘.

- 대상 사용자: 학생, 강사
- 목적: 마감 전 제출과 수정 이력을 명확히 관리하기 위해
- 핵심 행동: 과제 제출, 재제출, 제출 시간 확인, 제출 상태 확인
- 규칙: 마감 이후에는 제출할 수 없다
- 규칙: 학생은 자신의 제출만 볼 수 있다
- 기대 결과: 강사는 누가 언제 어떤 버전으로 제출했는지 확인할 수 있어야 한다

나쁜 입력과 이유

나쁜 예 1

React와 FastAPI로 태그 기능을 만들어줘.

문제점:

  • 기술 스택이 먼저 나옵니다.
  • 사용자 문제와 수용 기준이 없습니다.
  • plan 단계와 뒤섞입니다.

나쁜 예 2

좋은 Todo 앱을 만들어줘.

문제점:

  • 너무 추상적입니다.
  • 사용자 행동과 규칙이 없습니다.
  • clarify 질문이 과도하게 늘어날 수 있습니다.

생성 후 반드시 볼 것

  1. 사용자 시나리오가 있는가
  2. 수용 기준이 테스트 가능한 문장인가
  3. 기술 구현 디테일이 과하게 섞이지 않았는가
  4. [NEEDS CLARIFICATION] 마커가 어디에 붙었는가

[NEEDS CLARIFICATION]가 붙는 대표 사례

  • 태그 최대 개수 미정
  • 정렬 기준 미정
  • 권한 범위 미정
  • 삭제가 영구 삭제인지 숨김 처리인지 미정

이 마커는 문서가 잘못됐다는 뜻이 아니라, 아직 팀이 합의해야 할 질문이 남았다는 뜻입니다.

이 마커는 누가 언제 붙이는가

보통 처음 이 마커를 붙이는 주체는 /speckit.specify를 실행한 AI입니다. 사용자가 입력한 기능 설명 안에 빠진 조건, 모순되는 규칙, 해석이 둘 이상 가능한 표현이 있으면 AI가 여기는 아직 확정된 요구사항으로 쓰기 어렵다고 판단해서 spec 문장 안에 [NEEDS CLARIFICATION]를 남깁니다.

하지만 AI만 붙일 수 있는 것은 아닙니다. 사람이 spec.md를 검토하다가 아직 합의되지 않은 항목을 발견하면 직접 이 마커를 추가해도 됩니다. 중요한 것은 애매함을 숨기지 않고 드러내는 표시로 쓰는 것입니다.

즉, 붙는 시점은 대개 두 가지입니다.

  1. /speckit.specify가 초안을 만들 때
  2. 사람이 초안을 리뷰하면서 빠진 질문을 발견했을 때

이 마커는 왜 사용하는가

이 마커의 목적은 문서를 멈추게 하는 것이 아니라, 지금 바로 구현으로 내려가면 위험한 질문이 남아 있다는 사실을 팀이 보게 만드는 것입니다.

이 마커가 있으면 다음과 같은 효과가 있습니다.

  • plan 단계에서 추측으로 설계를 고정하는 일을 줄일 수 있습니다.
  • tasks 단계에서 잘못된 전제를 기준으로 작업을 쪼개는 일을 줄일 수 있습니다.
  • 구현 단계에서 원래 이게 어떤 뜻이었지?라는 혼선을 줄일 수 있습니다.
  • 나중에 requirement drift가 생겼을 때, 원래 미확정 항목이 무엇이었는지 추적할 수 있습니다.

한마디로 말하면, 이 마커는 문제 표시가 아니라 합의가 필요한 질문 목록의 시작점입니다.

어떤 경우에 반드시 남겨 두는 것이 좋은가

다음과 같은 경우에는 억지로 추측해서 채우기보다 마커를 남기는 편이 낫습니다.

  • 숫자 제한이 필요한데 최대값이나 최소값이 없음
  • 권한 규칙이 중요한데 사용자별 범위가 빠져 있음
  • 삭제, 취소, 만료 같은 상태 변화의 의미가 불명확함
  • 성공 기준은 있는데 실패 처리 규칙이 없음
  • 동일 용어를 서로 다르게 해석할 수 있음

예를 들어 사용자는 파일을 업로드할 수 있다는 문장만 있으면 파일 크기 제한, 허용 형식, 실패 시 메시지, 재시도 여부 등이 빠져 있을 수 있습니다. 이런 경우는 plan으로 내려가서 기술적으로 메우기보다 먼저 clarify가 필요합니다.

이 마커가 붙은 뒤에는 무엇을 해야 하는가

[NEEDS CLARIFICATION]가 보이면 가장 먼저 해야 할 일은 누가 답해야 하는 질문인지를 분리하는 것입니다.

  • 제품 요구사항 판단이면 사용자, 기획자, PO, 강사 같은 요구사항 결정권자가 답해야 합니다.
  • 도메인 규칙 판단이면 업무 담당자나 도메인 지식 보유자가 답해야 합니다.
  • 단순 표현 정리라면 작성자나 리뷰어가 즉시 문장을 고쳐도 됩니다.

실무 흐름으로 보면 보통 다음 순서가 자연스럽습니다.

  1. spec에서 [NEEDS CLARIFICATION] 위치를 표시한다.
  2. 질문을 문장으로 분리한다.
  3. 누가 답할지 정한다.
  4. 답을 받은 뒤 spec 문장을 확정형으로 고친다.
  5. 그때 plan과 tasks로 내려간다.

이 마커는 언제 누가 제거하는가

이 마커는 질문에 대한 합의가 끝났을 때 제거합니다. 제거 주체는 한 명으로 고정되지 않습니다.

  • AI가 clarify 결과를 반영하며 제거할 수도 있습니다.
  • 사람이 회의나 리뷰 결과를 반영하면서 제거할 수도 있습니다.
  • 경우에 따라 /speckit.specify를 다시 실행해 확정된 요구사항으로 새 spec을 만들면서 사라질 수도 있습니다.

다만 제거 기준은 분명해야 합니다. 대충 이 정도면 되겠지가 아니라 아래 조건 중 하나를 만족해야 합니다.

  • 요구사항 결정권자가 명확한 답을 줬다.
  • 문서에 수치, 범위, 조건, 예외가 구체적으로 적혔다.
  • 같은 질문이 다시 나오지 않을 정도로 문장이 검토 가능하게 바뀌었다.

즉, 이 마커를 지우는 사람보다 더 중요한 것은 지워도 되는 근거가 있는가입니다.

제거하면 안 되는 경우도 있다

초안 단계에서 답을 모르는 상태인데 보기 싫다는 이유로 마커를 지우면 안 됩니다. 그 경우 애매함이 사라지는 것이 아니라 숨겨질 뿐입니다.

특히 아래 상황에서는 제거를 미루는 편이 맞습니다.

  • 아직 stakeholder 답변을 받지 못함
  • 팀 내부 해석이 둘 이상으로 갈림
  • 구현은 시작했지만 요구사항 자체는 확정되지 않음

이럴 때는 마커를 남긴 채 질문 목록을 관리하는 편이 더 안전합니다.

교육 관점에서 이해하면

이 과정에서 [NEEDS CLARIFICATION]는 AI가 못해서 남긴 흔적이 아닙니다. 오히려 AI가 멋대로 결정하지 않고, 사람이 답해야 할 요구사항 경계를 보존했다는 뜻에 가깝습니다. 따라서 학습자는 이 마커를 보면 문서가 실패했다고 보기보다 여기서부터는 팀 합의가 필요하다고 읽는 것이 맞습니다.

실습 단계

  1. /speckit.specify를 실행합니다. 이 저장소에서는 before_specify hook가 먼저 실행되어 feature 브랜치를 자동으로 만들고 그 브랜치로 이동한 뒤 spec 생성이 진행됩니다. 즉, /speckit.specify가 끝났을 때는 보통 이미 001-todo-tagging 같은 브랜치 위에 있습니다.
    • specs/<번호>-<기능명>/spec.md: 이번 기능의 요구사항 본문입니다. 가장 중요하게 읽고 수정할 파일입니다.
    • specs/<번호>-<기능명>/checklists/requirements.md: spec 품질 체크리스트입니다. 빠진 항목이나 모호함이 없는지 확인하는 용도입니다.
    • .specify/feature.json: 현재 활성 feature 디렉터리를 가리키는 포인터 파일입니다.
  2. 이때 보통 다음 파일이 함께 생성됩니다.
  3. 생성된 spec.md를 읽으며 사용자 시나리오, acceptance scenario, 성공 기준, [NEEDS CLARIFICATION] 위치를 확인합니다.
  4. requirements.md를 함께 보면서 체크리스트가 실제 spec 내용과 맞는지 검토합니다.
  5. 기능 요구와 기술 선택이 섞인 문장, 모호한 표현, 테스트하기 어려운 문장이 있으면 spec.md에서 바로 정리합니다.
  6. .specify/feature.json은 보통 직접 수정하지 않고, 현재 작업 중인 feature 디렉터리를 올바르게 가리키는지만 확인합니다.
  7. 검토가 끝나면 현재 feature 브랜치에서 commit한 뒤 main에 merge합니다.

이 단계에서 실제로 무엇을 바꾸는가

사람이 가장 많이 손보는 파일은 spec.md입니다.

  • spec.md: 적극적으로 읽고 고치고 질문을 남기고 문장을 다듬는 핵심 문서입니다.
  • requirements.md: 직접 새로 쓰기보다 체크 결과가 spec과 맞는지 검토하는 보조 문서입니다.
  • .specify/feature.json: 보통 수정 대상이 아니라 현재 feature 경로 확인용 파일입니다.

즉, /speckit.specify 실행 후 해야 할 핵심 작업은 생성된 spec을 검토해서 요구사항을 더 정확하고 테스트 가능하게 다듬는 것입니다.

specs/001-todo-tagging와 001-todo-tagging는 무엇이 다른가

  • specs/001-todo-tagging: spec 결과물이 저장되는 feature 디렉터리입니다.
  • 001-todo-tagging: 이 저장소에서 /speckit.specify 실행 전에 자동 생성되는 feature 브랜치 이름 예시입니다.

즉, 하나는 파일 경로이고 다른 하나는 Git 작업 공간 이름입니다. 둘은 꼭 같은 이름일 필요는 없지만, 지금 내가 어느 feature 디렉터리를 기준으로 작업 중인지와 어느 Git 브랜치에서 검토 중인지는 분명히 구분해야 합니다.

Git 반영 예시

git status
git add specs/001-todo-tagging .specify/feature.json
git commit -m "docs: define feature spec"
git checkout main
git merge --no-ff 001-todo-tagging -m "merge: feature spec"
git push origin main

이 블록은 생성된 spec을 검토하고 다듬은 뒤, 현재 feature 브랜치의 결과를 main에 합의된 상태로 반영하는 절차입니다.

순서를 짧게 읽으면 다음과 같습니다.

  1. git status 현재 브랜치와 변경 파일 상태를 확인한다.
  2. git add specs/001-todo-tagging .specify/feature.json 이번 spec 산출물과 feature 포인터만 커밋 대상으로 올린다.
  3. git commit -m "docs: define feature spec" 이번 기능 요구사항을 하나의 문서 이력으로 기록한다.
  4. git checkout main 기준 브랜치로 돌아와 merge를 준비한다.
  5. git merge --no-ff 001-todo-tagging -m "merge: feature spec" feature 브랜치 결과를 merge commit으로 main에 반영한다.
  6. git push origin main 로컬에서 확정한 spec 이력을 원격 저장소와 공유한다.

실행하면서 실제로 확인해야 하는 것

  • /speckit.specify 직후 현재 브랜치가 001-todo-tagging 같은 feature 브랜치인지 확인합니다.
  • git status에서는 specs/001-todo-tagging/와 .specify/feature.json 등 spec 생성과 직접 관련된 파일만 바뀌었는지 봅니다.
  • git add specs/001-todo-tagging .specify/feature.json 후에는 staging 영역에 의도하지 않은 파일이 섞이지 않았는지 다시 확인합니다.
  • git commit이 끝나면 docs: define feature spec 메시지로 커밋이 하나 생겼는지 확인합니다.
  • git checkout main 후에는 정말 main 브랜치로 돌아왔는지 확인합니다.
  • git merge --no-ff ... 후에는 merge commit이 남아 spec 초안이 main에 합의되어 들어왔다는 사실이 이력에 보이는지 확인합니다.
  • git push origin main 후에는 원격 저장소에서도 spec 반영 결과를 볼 수 있어야 합니다.

왜 여기서는 git checkout -b ...를 다시 하지 않는가

이 저장소는 /speckit.specify 실행 전에 before_specify hook가 먼저 동작합니다. 그래서 명령을 실행하면 Git feature 브랜치가 자동 생성되고 그 브랜치에서 spec 작업이 진행됩니다. 이미 feature 브랜치 위에 올라와 있는 상태에서 다시 새 브랜치를 만들면 같은 작업을 한 번 더 분리하는 셈이어서 오히려 흐름이 복잡해집니다.

자주 헷갈리는 포인트

git add specs/001-todo-tagging .specify/feature.json만으로 충분한가

이 예시는 /speckit.specify가 실제로 만든 핵심 산출물만 올리는 가장 보수적인 예시입니다. 다만 실제 실습에서는 spec.md 설명을 보완한 학습 문서나 다른 관련 파일이 함께 바뀔 수도 있으므로, 그 경우에는 git status를 보고 필요한 파일을 선택적으로 추가해야 합니다. 핵심은 전체 add가 아니라 이번 spec 작업과 직접 관련된 파일만 올린다는 점입니다.

왜 --no-ff를 붙이는가

나중에 Git 로그를 볼 때 여기서 feature spec이 main에 합의되어 들어왔다는 시점을 명확히 남기기 위해서입니다. 단순 fast-forward보다 교육용 기록과 검토 흐름을 설명하기 좋습니다.

왜 바로 구현하지 않고 spec을 먼저 merge하는가

spec은 구현 전에 무엇을 만들 것인가를 먼저 합의하는 단계입니다. 이 문서가 먼저 안정되어야 이후 plan과 tasks가 흔들리지 않습니다. 그래서 spec 자체를 하나의 독립 산출물처럼 다루는 연습이 중요합니다.

스스로 점검

  1. 이 spec은 개발자가 아니라 사용자 관점에서도 읽을 수 있는가?
  2. 구현 방식이 아니라 기대 동작이 중심인가?
  3. clarifiy가 필요한 부분이 자연스럽게 드러나는가?