“AI랑 핑퐁하다 하루 끝” 이제 그만: `/spec` 하나로 명세서→구현→검증까지 끝내기

LinkDropper·2025년 12월 23일

Others

목록 보기
6/9
post-thumbnail

들어가며

지난 글에서 Claude Code의 Custom Commands로 구현부터 PR까지 자동화한 이야기를 했어요.
오늘은 그중에서도 제 워크플로우의 심장 같은 존재, /spec 명령어를 깊게 파헤쳐보려고 합니다.

솔직히 AI 코딩 도구를 쓰면서 이런 답답함, 한 번쯤 느끼셨을 거예요.

  • “코드는 만들어주는데… 왜 이렇게 만들었는지 모르겠어”
  • “요청한 것만 딱 만들고 끝. 나머지는 결국 내가 마무리해야 해”
  • “날마다 결과물이 들쭉날쭉해서, 다시 손대느라 시간이 더 든다”

/spec은 이 문제를 ‘명세서 기반 개발’로 정면 돌파합니다.

AI에게 “구현해줘”라고 말하는 대신,
결정을 명세서에 미리 담고 /spec으로 실행한다.

이 한 줄이 생각보다 큰 차이를 만들더라고요.


/spec이 뭔가요?

한 줄 요약은 이렇게 할게요.

명세서를 주면, Claude가 분석→계획→구현→검증→보고까지 “개발 프로세스”를 그대로 수행하는 명령어

/spec user-auth  # specs/user-auth.md를 읽고 구현

그리고 여기서 가장 중요한 키워드가 하나 있습니다.

“질문 없이”

보통 AI에게 기능 구현을 부탁하면 이런 흐름이 반복되죠.

AI: "인증은 JWT로 할까요? 세션으로 할까요?"
나: "JWT요"
AI: "토큰 저장은 어디에 할까요?"
나: "AsyncStorage요"
AI: "에러 처리는 어떻게 할까요?"
나: (이미 지침)

/spec은 이 핑퐁을 줄이는 게 아니라, 애초에 필요 없게 만들어요.

  • 선택지를 AI가 묻기 전에
  • 사람이 답변하느라 흐름이 끊기기 전에
  • 명세서에 결정을 박아두는 방식입니다.

/spec이 동작하는 핵심 원칙 4가지

/spec은 “코드 생성”이라기보다, 코드를 만들기 위한 규칙 세트에 가까워요.

1) 명세서만으로 끝나야 한다

명세서가 충분히 상세하면 Claude는 추가 질문 없이 구현에 들어갑니다.
즉 명세서는 단순 문서가 아니라 실행 가능한 문서가 됩니다.

2) 품질을 기본값으로 둔다

“일단 돌아가는 코드”가 아니라

  • 가독성
  • 성능
  • 확장성
  • 보안

까지 기본값으로 깔고 들어가요. 목표는 프로덕션에 올려도 부끄럽지 않은 코드입니다.

3) 우선순위 기반으로 구현한다 (🔴→🟡→🟢)

필수부터 먼저 완성하고, 시간이 남으면 권장/선택 기능으로 넘어갑니다.
이 구조 덕분에 “시간이 부족해서 다 못 했어요”여도 핵심 기능은 살아있어요.

4) 한 명령어는 한 가지 일만

테스트는 /create-jest, 문서는 /w-context로 분리했어요.
/spec구현과 검증에만 집중합니다.


/spec 실행 흐름: Phase 0 → Phase 6

/spec이 “그냥 생성”이 아니라 “개발 프로세스”인 이유가 여기 있어요.
총 7단계를 항상 같은 순서로 밟습니다.

Phase 0: 명세서 로드
Phase 1: 명세서 분석 및 이해
Phase 2: 구현 전 검토 (질문 필요 시)
Phase 3: 구현 계획 수립
Phase 4: 코드 구현
Phase 5: 검증
Phase 6: 완료 보고

각 단계를 짧게(하지만 핵심은 빠짐없이) 살펴볼게요.


Phase 0: 명세서 로드

/spec              # 인자 없이 실행하면 목록 표시
/spec user-auth    # specs/user-auth.md 로드
  • 인자가 없으면 사용 가능한 명세서 목록을 보여주고
  • 인자가 있으면 해당 파일을 불러옵니다.

파일이 없으면 이렇게 깔끔하게 실패합니다.

❌ specs/user-auth.md 파일을 찾을 수 없습니다.
사용 가능한 명세서: [목록]

Phase 1: 명세서 분석 및 이해

이 단계가 품질을 결정합니다.
Claude가 바로 코딩부터 하지 않고, 명세서에서 필요한 정보를 구조적으로 뽑아내요.

섹션뽑아내는 정보
개요기능 목적, 해결하려는 문제
사용자 시나리오플로우/유스케이스
기능 요구사항🔴 필수 → 🟡 권장 → 🟢 선택 정렬
구현 위치생성/수정할 파일 경로
기존 코드 활용참고할 패턴/모듈
타입 정의인터페이스/타입
API 설계엔드포인트, 요청/응답
에러 처리에러 코드/메시지/처리

그리고 여기서 중요한 한 가지.

CONTEXT.md를 같이 읽습니다

기존 코드의 설계 의도와 사용 패턴을 놓치면 “프로젝트랑 따로 노는 코드”가 나오거든요.

# 예: libs/fetch 모듈을 활용한다면
cat libs/fetch/CONTEXT.md

이 과정을 넣어두니, 결과물이 “그럴듯한 예제 코드”가 아니라 우리 코드베이스의 일부처럼 나오기 시작했습니다.


Phase 2: 구현 전 검토 (질문이 정말 필요한지 판단)

/spec이 “질문이 없다”는 건 무조건 묻지 않는다가 아니라,
정말 필요한 경우에만 묻도록 설계했다는 뜻입니다.

질문하는 경우

  • 구현 위치가 불명확하거나 선택지가 여럿인 경우
  • 기존 코드와 충돌 가능성이 큰 경우
  • 보안/성능에 큰 트레이드오프가 있는 경우

질문 없이 진행하는 경우

  • 명세서가 충분히 구체적인 경우
  • 컨벤션(CLAUDE.md)으로 답이 이미 정해지는 경우
  • 업계 표준 베스트 프랙티스가 명확한 경우

여기서 얻은 인사이트는 딱 하나였어요.

질문이 많이 나온다면 /spec이 문제라기보다, 명세서가 덜 익은 것이다.


Phase 3: 구현 계획 수립 (Todo 리스트 자동 생성)

명세서 요구사항을 바탕으로 Todo를 뽑고, 우선순위를 고정합니다.

1. 🔴 필수 요구사항 (모두 완료해야 함)
2. 🟡 권장 요구사항 (시간이 허락하면)
3. 🟢 선택 요구사항 (추가 개선)

그리고 보통 이런 흐름으로 구현 순서를 잡아요.

1. 타입 정의
2. 에러/결과 모델
3. 핵심 로직
4. 유틸리티
5. API 라우트
6. UI 컴포넌트
7. 페이지 통합
8. export 정리

타입부터 잡아두면 이후 구현이 안정적으로 굴러가서, 결과적으로 수정량이 줄었습니다.


Phase 4: 코드 구현 (하지만 “아무렇게나”는 금지)

여기서는 명세서 + 컨벤션을 근거로 구현합니다.
원칙은 딱 5가지로 고정했어요.

  • 컨벤션 준수 (네이밍, import 순서, 코드 스타일)
  • 성능 고려 (불필요 연산/렌더 최소화)
  • 가독성 고려 (단일 책임, 명확한 이름, 필요한 곳만 주석)
  • 확장성 고려 (인터페이스 기반, 하드코딩 지양)
  • 보안 고려 (입력 검증, 민감 정보 노출 방지)

이게 좋아서라기보다, 원칙이 고정돼 있으니 결과가 안정적입니다.


Phase 5: 검증 (여기서 “진짜 자동화”가 갈립니다)

코드만 만들고 끝내면 AI 도구가 아니라 “코드 생성기”죠.
/spec은 검증을 기본 프로세스에 넣었습니다.

pnpm build   # 타입 체크
pnpm lint    # 린트 체크
pnpm test -- <관련 테스트 경로>  # 관련 테스트 (필요 시)

그리고 중요한 포인트.

에러가 나면 “에러 났어요”로 끝나는 게 아니라, 수정 후 재시도합니다.

이 부분 때문에 “결과물의 신뢰도”가 확 올라갔어요.


Phase 6: 완료 보고 (사람이 바로 판단 가능하게)

마지막에 구조화된 보고서를 출력합니다. 예시는 이런 느낌이에요.

## ✅ 구현 완료: 사용자 인증

### 요약
> 소셜 로그인을 통한 사용자 인증 시스템

### 구현된 요구사항
- [x] 🔴 Apple 로그인
- [x] 🔴 Google 로그인
- [x] 🟡 자동 로그인

### 생성된 파일
| 파일 | 설명 |
|------|------|
| `libs/auth/types.ts` | 타입 정의 |
| `libs/auth/core.ts` | 핵심 로직 |

### 검증 결과
| 항목 | 결과 |
|------|------|
| 타입 체크 | ✅ 통과 |
| 린트 | ✅ 통과 |

### 사용 예시
```typescript
import { signInWithApple } from "@/libs/auth";

const user = await signInWithApple();

다음 단계

/create-jest
/w-context

덕분에 “뭐가 됐고, 뭐가 남았고, 다음은 뭘 하면 되는지”가 한눈에 들어옵니다.

---

## 좋은 명세서 작성법: 질문을 0에 가깝게 만드는 체크리스트

`/spec` 품질은 결국 **명세서 품질**에 달려있습니다.  
제가 가장 효과를 봤던 팁들만 모아볼게요.

### 1) 구현 위치를 무조건 적는다
```markdown
## 구현 위치

### 생성할 파일
- `libs/auth/types.ts`
- `libs/auth/core.ts`
- `libs/auth/index.ts`

### 수정할 파일
- `stores/authStore.ts`

경로가 없으면 100% “어디에 만들까요?”가 나옵니다.

2) 타입을 명세서에 박아두기

## 타입 정의

```typescript
interface AuthUser {
  id: string;
  email: string;
  name: string;
  provider: 'apple' | 'google' | 'kakao';
}

타입이 있으면 결과물이 흔들리지 않아요. (그리고 나중에 타입 수정 지옥이 줄어듭니다.)

### 3) 에러 케이스는 표로 정리
```markdown
## 에러 처리

| 상황 | 코드 | 사용자 메시지 | 처리 |
|---|---|---|---|
| 네트워크 끊김 | NETWORK_ERROR | 인터넷 연결을 확인해주세요 | 재시도 |
| 토큰 만료 | TOKEN_EXPIRED | 다시 로그인해주세요 | 로그인 이동 |

표로 쓰면 “빼먹는 에러”가 확 줄어듭니다.

4) 우선순위는 🔴🟡🟢로 고정

AI가 “어느 것부터?”를 고민할 필요가 없게 만드는 장치입니다.

5) “기존 코드 활용” 섹션을 꼭 둔다

## 기존 코드 활용

- `libs/api/client.ts` - API 호출 패턴 참고
- `stores/authStore.ts` - 상태 관리 패턴 참고

이게 있으면 결과물이 “우리 코드”에 훨씬 자연스럽게 붙습니다.


실제 명세서 예시 (일부)

제가 실제로 링크 드라퍼에서 사용한 명세서 일부입니다.

# 공유 익스텐션 메타데이터 크롤링

## 개요
iOS Share Extension에서 공유된 URL의 메타데이터를 크롤링하여
링크 정보를 자동으로 채우는 기능

## 기능 요구사항
### 🔴 필수
- Open Graph 메타데이터 추출
- 제목/설명/이미지 URL 파싱
- 타임아웃 및 에러 처리

### 🟡 권장
- 이미지 없을 시 파비콘 폴백
- 캐싱으로 중복 요청 방지

## 구현 위치
### 생성할 파일
- `libs/crawler/types.ts`
- `libs/crawler/parser.ts`
- `libs/crawler/index.ts`

## 타입 정의
```typescript
interface LinkMetadata {
  title: string | null;
  description: string | null;
  imageUrl: string | null;
  faviconUrl: string | null;
}

에러 처리

에러 상황처리 방법
네트워크 타임아웃5초 후 빈 메타데이터 반환
파싱 실패URL만 저장, 메타데이터는 null

이 정도만 적어도 `/spec`이 **질문 없이 구현**을 끝내는 편이었습니다.

---

## `/spec`이 바꾼 내 개발 방식

### Before: 대화형 개발(=핑퐁 지옥)
```text
나: "인증 기능 만들어줘"
AI: "어떤 방식으로?"
나: "소셜 로그인"
AI: "어떤 제공자?"
나: "Apple, Google"
AI: "토큰 저장은?"
나: (이때부터 집중력 붕괴)

After: 명세서 기반 개발(=실행)

나: "/spec user-auth"
AI: 분석 → 계획 → 구현 → 검증 → 보고
나: (검증 통과한 코드 받음)

시간이 줄어든 것도 좋았지만, 더 큰 변화는 이거였어요.

명세서가 같으면 결과도 비슷하다.
즉, 코드 품질이 ‘컨디션’이 아니라 ‘프로세스’에 의해 결정된다.


마치며

/spec은 단순히 “코드를 잘 뽑는 명령어”가 아니라,

  • 명세서를 실행 가능한 문서로 만들고
  • 개발 프로세스(분석→계획→구현→검증)를 강제하고
  • 결과물의 품질을 안정화하는 장치였습니다.

명세서를 쓰는 시간이 들긴 해요.
그런데 그 시간은 대부분 “AI와 핑퐁하며 잃는 시간”을 통째로 대체하더라고요.

다음 글(3편)에서는 /create-jest를 다룹니다.
/spec으로 만든 코드에 테스트를 자동으로 붙이는 흐름이 어떻게 굴러가는지 공유해볼게요.


시리즈 안내

순서제목상태
1편Claude Code Commands로 개발 워크플로우 자동화하기✅ 완료
2편/spec - 명세서 기반 코드 구현 자동화✅ 현재 글
3편/create-jest - 테스트 코드 자동 생성예정
4편/w-context - AI를 위한 문서 작성예정
5편/pr + /apply-review - PR 워크플로우 자동화예정

링크 드라퍼, 정식 출시!

링크 드라퍼는 단순 저장 툴이 아니라, “다시 꺼내보게 만드는” 링크 관리 도구를 지향합니다.

  • 빠르고 간편한 링크 저장: iOS/Android 앱, 웹, 크롬 익스텐션
  • 폴더로 깔끔하게 정리: 읽을 거리, 레퍼런스, 쇼핑 후보까지
  • 폴더 공유: 같이 보는 자료는 폴더 단위로 한 번에
  • 크롬 익스텐션 원클릭 저장: 보고 있는 페이지를 바로 저장

링크 드라퍼 앱 다운로드 (iOS)
링크 드라퍼 웹에서 사용하러 가기
크롬 웹스토어에서 익스텐션 설치하기

profile
“기록하는 습관을 도구로 만들다 — 두 개발자의 링크 드라퍼 구축기”

0개의 댓글