AI 시리즈 면접 16: 좋은 Spec Coding은 어떤 모습이어야 할까?
좋은 Spec Coding (사양 기반 프로그래밍)의 핵심은 '모호한 아이디어'를 '정확하고, 검증 가능하며, 실행 가능한 계약'으로 바꾸는 것입니다. 단순히 문서를 작성하는 것이 아니라, 사람과 AI(또는 사람과 사람) 사이의 모호함이 없는 의사소통 언어를 구축하는 것입니다. 아래에서는 사양의 내용 구조, 작성 원칙, AI와의 협업 프로세스, 품질 검증의 네 가지 차원에서 좋은 Spec의 모습을 제시합니다.
1. 사양 문서의 표준 구조 (기능 모듈 예시)
| 섹션 | 필수 내용 | 예시 |
|---|---|---|
| 1. 목표 및 범위 | 한 문장으로 무엇을 하는지, 무엇을 하지 않는지 명확히 | '사용자 등록 API 구현, 이메일 인증은 포함하지 않음' |
| 2. 입력/출력 계약 | 데이터 구조, 타입, 필수/선택 필드, 예시 값 | POST /register 요청 본문 {email: string, password: string}, 응답 201 또는 400 (오류 코드 포함) |
| 3. 동작 및 로직 | 비즈니스 규칙, 경계 조건, 상태 전환 | '비밀번호 길이 8~20자, 숫자 1개 이상 포함; 이메일이 이미 존재하면 409 반환' |
| 4. 오류 처리 | 가능한 모든 예외 시나리오 및 해당 오류 코드/메시지 | '데이터베이스 연결 실패 → 503 반환, 스택 추적 노출 금지' |
| 5. 비기능 요구사항 | 성능(응답 시간 < 200ms), 보안(매개변수화 쿼리), 로깅, 관찰 가능성 | '모든 SQL은 사전 컴파일 사용; email은 기록하지만 password는 기록하지 않음' |
| 6. 테스트 케이스 (중요) | 최소 3개의 일반 입력 + 2개의 경계/예외 입력, 예상 출력 제시 | 아래 표 참조 |
| 7. 의존성 및 제약 | 사용할 라이브러리, 버전, 환경 변수 | 'Python 3.10+, FastAPI, 환경 변수 DB_URL' |
테스트 케이스 예시 (spec에 포함)
| 시나리오 | 입력 | 예상 출력 |
|---|---|---|
| 정상 등록 | email: a@b.com, pwd: Pass1234 |
201, user_id 반환 |
| 비밀번호 너무 짧음 | pwd: Ab1 |
400, 오류 코드 WEAK_PASSWORD |
| 이메일 이미 존재 | 위와 동일한 email | 409, 오류 코드 EMAIL_EXISTS |
좋은 Spec은 먼저 테스트 케이스를 작성해야 합니다. AI가 이를 기반으로 유닛 테스트를 직접 생성하고, 완료 후 자동으로 검증할 수 있기 때문입니다.
2. Spec 작성의 핵심 원칙 (SMART 변형)
| 원칙 | 설명 | 반례 |
|---|---|---|
| 정확성 (Precise) | 구체적인 숫자, 타입, 불리언 조건 사용. '가능한', '일반적으로' 회피 | ❌ '비밀번호는 충분히 안전해야 함' → ✅ '비밀번호는 최소 8자, 대문자, 소문자, 숫자 포함' |
| 검증 가능성 (Verifiable) | 모든 요구사항이 자동 테스트 또는 수동 확인으로 통과/실패 판단 가능 | ❌ '코드는 우아해야 함' → ✅ '함수 순환 복잡도 ≤ 10, 중복 코드 블록 없음' |
| 모호함 없음 (Unambiguous) | 동일 용어가 전체에서 일관된 의미로 사용, 필요시 용어집 제공 | ❌ '사용자가 존재하지 않으면 오류 반환' → ✅ '사용자 없음 → 404 및 {code: 'USER_NOT_FOUND'} 반환' |
| 완전성 (Complete) | 해피 패스, 모든 예외 경로, 비기능 요구사항 포함 | ❌ 성공 시나리오만 작성 → ✅ 데이터베이스 타임아웃, 권한 부족 등 포함 |
| 원자성 (Atomic) | 하나의 spec은 독립적으로 전달 가능한 하나의 기능만 설명 (AI가 한 번에 완료하기 쉽도록) | ❌ 하나의 spec으로 '전체 결제 시스템' 작성 → ✅ '결제 주문 생성', '콜백 서명 검증', '환불'로 분할 |
3. AI와 협업 시 Spec Coding 프로세스
- 사람이 spec 작성 (위 구조, 특히 테스트 케이스와 함수 시그니처를 잘 작성).
- spec을 AI에게 한 번에 전달 (대화식으로 요구사항 추가하지 않음, 바이브 오염 방지).
- AI가 코드 + 유닛 테스트 출력 (AI는 spec의 테스트 케이스를 따라 실행 가능한 테스트를 생성해야 함).
- 테스트 실행: 모두 통과하면 다음 단계로; 통과하지 못하면 spec 수정 또는 코드 직접 수정 (이때 작은 루프 가능, 단 변경 기록 필요).
- 인적 검토: spec 외 기능 도입 여부(scope creep) 확인, 보안/성능 점검.
- 고정: spec 문서와 최종 코드를 함께 저장소에 커밋하여 영구 문서로 유지.
핵심 실천: Spec 코드화 —
spec.md+test_spec.py사용. 테스트 파일은 spec의 예제에서 직접 가져와, 이후 코드 수정 시 테스트만 실행하면 spec이 훼손되었는지 검증 가능.
4. 좋은 Spec이 가져오는 효과 (수용 기준으로 사용 가능)
- 결정성: 동일한 spec을 다른 AI(또는 다른 사람)에게 주면 유사한 구현이 나옴.
- 테스트 가능성: 코드 작성 직후 90%의 정확성을 자동으로 검증 가능.
- 유지보수성: 6개월 후 누구나 spec을 보면 당시의 설계 의도를 이해할 수 있음.
- 낮은 커뮤니케이션 비용: 팀 논의 시 spec만 논의하고 구체적인 코드 줄은 논의하지 않음.
- 보안/품질 내장: 보안 요구사항(예: 매개변수화 쿼리)과 경계 조건이 spec에 명시되어 AI가 준수해야 함.
5. 좋은 Spec의 예시 (간소화 버전)
# Spec: 사용자 등록 API
## 범위
- email, password 수신
- 인증 메일 발송 안 함, 이메일 실제 존재 여부 확인 안 함
## 계약
POST /register
Content-Type: application/json
Request: { "email": string, "password": string }
Response 201: { "user_id": string }
Response 400: { "code": "INVALID_PASSWORD" | "INVALID_EMAIL" }
Response 409: { "code": "EMAIL_ALREADY_EXISTS" }
## 동작
- email은 RFC 5322 기본 형식(a@b.c)을 따라야 함
- password: 길이 8~20, 숫자 1개 이상 및 대문자 1개 이상 포함
- bcrypt로 암호화 저장, salt 비용 10
- 데이터베이스 저장 전 email이 이미 존재하면 → 409
## 테스트 케이스 (입력 -> 예상 상태 코드+응답 필드)
| 입력 email | password | 예상 |
|------------|----------|------|
| test@x.com | Pass1234 | 201, user_id 존재 |
| test@x.com | pass | 400, INVALID_PASSWORD |
| bad | Pass1234 | 400, INVALID_EMAIL |
| (이미 존재하는 이메일) | Pass1234 | 409, EMAIL_ALREADY_EXISTS |
## 비기능
- SQL은 반드시 매개변수화 쿼리 사용 (인젝션 방지)
- 로그에 등록 출처 IP 기록, password는 기록하지 않음
- 응답 시간 95% 요청 < 100ms (bcrypt 제외)
## 의존성
- Python 3.10+, FastAPI, bcrypt, asyncpg
좋은 Spec Coding = 사람의 '설계 결정'을 기계의 '테스트 케이스 + 타입 시그니처 + 행동 제약'으로 변환하여 AI는 구현만 채우고, 사람은 항상 품질과 방향을 통제하는 것입니다.
评论
暂无已展示的评论。
发表评论(匿名)