Spec-First 워크플로우
바이브 코딩의 이상적인 루프: 명세 먼저, 테스트 다음, 코드는 마지막. 실전 워크플로우와 CLAUDE.md 활용법을 다룬다.
지난 글에서 "개발 감독"이 해야 할 일을 정리했다. 요구사항 명확화, 구조 설계, 품질 검증, 방향 조정.
이번 글에서는 이걸 실제로 어떻게 하는지 구체적인 워크플로우를 다룬다. 핵심은 Spec-First - 명세 먼저, 코드는 나중.
왜 Spec-First인가
바이브 코딩에서 흔히 하는 실수:
"로그인 만들어줘"
→ 뭔가 나옴
→ "아 이거 말고"
→ 수정
→ "이것도 아닌데"
→ 수정
→ (반복)
이게 왜 비효율적이냐면, 피드백이 구현 이후에 일어나기 때문이다. 뭘 만들지 명확하지 않은 상태에서 시작하니까 계속 수정하게 된다.
Spec-First는 순서를 바꾼다:
1. 뭘 만들지 명세를 먼저 쓴다
2. 이걸 만족하는지 확인할 테스트를 정의한다
3. 그 다음에 구현을 시킨다
이러면 "아 이거 말고"가 훨씬 줄어든다.
Spec-First 루프
전체 흐름은 이렇다.
┌─────────────────────────────────────────┐
│ 1. Spec (명세) │
│ - 무엇을 만들 것인가 │
│ - 입력/출력은 무엇인가 │
│ - 성공/실패 조건은 무엇인가 │
└────────────────┬────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 2. Test (테스트 정의) │
│ - 이 기능이 잘 동작하면 뭐가 되어야 하나 │
│ - 테스트 케이스 목록 │
└────────────────┬────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 3. Code (구현) │
│ - AI에게 Spec + Test 전달 │
│ - 구현 요청 │
└────────────────┬────────────────────────┘
↓
┌─────────────────────────────────────────┐
│ 4. Verify (검증) │
│ - 테스트 통과? │
│ - 스펙 만족? │
│ - 문제 있으면 3으로 │
└─────────────────────────────────────────┘
1단계: Spec 작성
Spec은 "무엇을 만들 것인가"를 명확히 정의하는 문서다.
좋은 Spec의 구성
## 기능: 사용자 로그인
### 목적
사용자가 이메일/비밀번호로 로그인할 수 있다.
### 입력
- email: string (필수, 이메일 형식)
- password: string (필수, 8자 이상)
### 출력
- 성공: { user: User, token: string }
- 실패: { error: string, code: string }
### 동작
1. 이메일로 사용자 조회
2. 없으면 에러 반환 (USER_NOT_FOUND)
3. 비밀번호 검증
4. 틀리면 에러 반환 (INVALID_PASSWORD)
5. 맞으면 토큰 생성 후 반환
### 에러 케이스
- 이메일 형식 아님 → INVALID_EMAIL
- 비밀번호 8자 미만 → INVALID_PASSWORD_FORMAT
- 사용자 없음 → USER_NOT_FOUND
- 비밀번호 틀림 → INVALID_PASSWORD이 정도 쓰면 AI가 뭘 만들어야 하는지 명확히 안다. "로그인 만들어줘"랑은 결과가 다를 수밖에 없다.
Spec 작성 팁
- 입력/출력을 명확히: 타입까지 적으면 좋다
- 에러 케이스 먼저 생각: 해피 패스만 적지 말고
- 경계 조건 포함: "8자 이상"이면 7자일 때 뭐가 되나?
- 짧게 유지: 너무 길면 읽기 싫다
2단계: Test 정의
Spec을 바탕으로 테스트 케이스를 정의한다. 아직 테스트 코드를 쓰는 게 아니라, 뭘 테스트할 건지 목록을 만든다.
## 테스트 케이스
### 성공 케이스
- [x] 올바른 이메일/비밀번호로 로그인 → user, token 반환
### 유효성 검사
- [x] 이메일 없이 요청 → INVALID_EMAIL
- [x] 이메일 형식 틀림 → INVALID_EMAIL
- [x] 비밀번호 없이 요청 → INVALID_PASSWORD_FORMAT
- [x] 비밀번호 7자 → INVALID_PASSWORD_FORMAT
- [x] 비밀번호 8자 → 통과
### 비즈니스 로직
- [x] 존재하지 않는 이메일 → USER_NOT_FOUND
- [x] 비밀번호 틀림 → INVALID_PASSWORD이 목록이 있으면 나중에 "구현이 맞는지" 확인하기 쉽다.
3단계: 구현 요청
이제 AI에게 구현을 시킨다. 이때 Spec과 테스트 케이스를 같이 전달한다.
아래 스펙에 맞는 로그인 API를 구현해줘.
[Spec 내용 붙여넣기]
다음 테스트 케이스가 모두 통과해야 해:
[테스트 케이스 목록 붙여넣기]
사용하는 스택:
- Next.js API Routes
- Supabase (DB)
- bcrypt (비밀번호 해싱)
이렇게 주면 AI가 스펙에 맞게 구현한다. 물론 한 번에 완벽하진 않지만, "아 이거 말고" 횟수가 확 줄어든다.
4단계: 검증
구현이 나오면 테스트 케이스 목록을 확인한다.
- 테스트 코드가 있으면 실행
- 없으면 수동으로 확인 (또는 AI에게 테스트 코드 작성 요청)
- 문제 있으면 구체적으로 피드백
테스트 결과:
- 성공 케이스: 통과
- 이메일 없이 요청: 실패 (500 에러 발생, INVALID_EMAIL 아님)
- 나머지: 확인 필요
"이메일 없이 요청" 케이스에서 INVALID_EMAIL을 반환하도록 수정해줘.
이런 식으로 구체적으로 피드백하면 수정이 빠르다.
CLAUDE.md: 프로젝트 컨텍스트 유지
Spec-First를 하다 보면 매번 반복되는 내용이 있다.
- "우리 프로젝트는 Next.js + Supabase야"
- "상태 관리는 Zustand 써"
- "컴포넌트는 src/components에 넣어"
- "API는 RESTful하게"
이걸 매번 말하기 귀찮다. 그래서 CLAUDE.md 같은 파일을 만든다.
# 프로젝트 컨텍스트
## 기술 스택
- Next.js 14 (App Router)
- Supabase (PostgreSQL)
- Tailwind CSS
- Zustand (상태관리)
- Vitest (테스트)
## 디렉토리 구조
- src/app: 페이지
- src/components: 컴포넌트
- src/lib: 유틸리티
- src/types: 타입 정의
## 코딩 컨벤션
- 컴포넌트: PascalCase
- 함수: camelCase
- 타입: interface 선호 (type보다)
- async 함수: *Async 접미사
## API 규칙
- RESTful
- 에러 응답: { error: string, code: string }
- 인증: Bearer token
## 테스트 규칙
- 파일 옆에 *.test.ts
- describe/it 구조
- 외부 의존성 모킹이 파일을 대화 시작할 때 첨부하거나, AI 도구 설정에 포함시키면 매번 말 안 해도 된다.
Claude Code 같은 경우 프로젝트 루트에 CLAUDE.md를 두면 자동으로 참조한다.
Thin Slice 전략
큰 기능을 한 번에 구현하려고 하면 망한다. 얇게 썰어서 하나씩 구현한다.
[안 좋은 예]
"회원 관리 시스템 만들어줘"
→ 너무 큼
→ 뭘 원하는지 모호
→ 결과도 모호
[좋은 예]
Slice 1: 회원 목록 조회 API
Slice 2: 회원 목록 페이지 (UI)
Slice 3: 회원 상세 조회 API
Slice 4: 회원 상세 페이지
Slice 5: 회원 수정 API
Slice 6: 회원 수정 폼
...
각 Slice마다 Spec-First 루프를 돈다. 하나가 끝나면 다음으로 넘어간다.
이렇게 하면:
- 피드백이 빠르다 (작은 단위로 확인)
- 방향 수정이 쉽다 (아직 안 만든 건 바꾸면 됨)
- 진행 상황이 보인다 (몇 개 했고 몇 개 남았는지)
실제 예시: 댓글 기능
실제로 내가 블로그 댓글 기능 만들 때 한 과정이다.
1. Spec
## 기능: 포스트 댓글
### 기능 목록
1. 댓글 작성
2. 댓글 목록 조회
3. 댓글 삭제 (작성자만)
### 데이터 구조
- id: string
- postSlug: string
- author: string
- content: string (최대 1000자)
- createdAt: timestamp2. Slice 분리
1. DB 테이블 생성
2. 댓글 작성 API
3. 댓글 목록 조회 API
4. 댓글 UI 컴포넌트
5. 댓글 삭제 기능
3. 각 Slice마다 Spec-First
Slice 2: 댓글 작성 API
[Spec]
- POST /api/comments
- body: { postSlug, author, content }
- content 1000자 초과 시 에러
- 성공 시 생성된 댓글 반환
[테스트]
- 정상 요청 → 댓글 생성
- content 없음 → 에러
- content 1001자 → 에러
- postSlug 없음 → 에러
이런 식으로 하나씩 진행했다.
도구 활용 팁
Claude Code
- /compact 모드로 긴 Spec도 효율적으로 처리
- CLAUDE.md에 프로젝트 규칙 정리
- TodoWrite로 Slice 목록 관리
Cursor
- .cursorrules 파일에 규칙 정리 (CLAUDE.md와 비슷)
- Composer로 여러 파일 동시 수정
- Inline edit으로 세부 조정
공통
- Spec은 별도 파일로 관리 (나중에 참조하기 좋음)
- 테스트 케이스 목록은 체크리스트로 유지
- 완료된 Slice는 커밋
마무리
Spec-First 워크플로우의 핵심:
- Spec 먼저 - 뭘 만들지 명확히
- 테스트 다음 - 어떻게 확인할지 정의
- 구현은 마지막 - AI에게 시킴
- 검증 - 테스트로 확인
- 반복 - Thin Slice로 하나씩
이게 "감독"이 하는 일이다. 직접 코드를 치는 대신, 구조를 잡고 검증한다.
다음 편에서는 테스트 전략을 더 깊게 다룬다. AI 코드를 어떻게 신뢰할 수 있게 만드는가.
바이브 코딩은 자유를 주지만, 책임은 사라지지 않는다.
이 글이 어떠셨나요?
관련 포스트
AI 코드를 신뢰하는 방법: 테스트 전략
테스트는 버그를 잡는 게 아니라 AI를 통제하는 수단이다. 바이브 코딩 시대의 테스트 피라미드와 실전 전략을 다룬다.
2026. 02. 08. 오후 10:00Development바이브 코딩 프로젝트의 6개월 후
바이브 코딩으로 만든 프로젝트의 지속 가능성. 기술 부채 청산, 유지보수, 그리고 진짜 "완성"이란 무엇인가.
2026. 02. 15. 오후 10:00Development1인 개발자의 바이브 코딩 시스템
혼자서 팀처럼 개발하는 법. CLAUDE.md, CI, 셀프 코드리뷰를 활용한 규칙 기반 솔로 개발 시스템을 구축한다.
2026. 02. 11. 오후 10:00뉴스레터 구독
새 글이 올라오면 이메일로 알려드려요.