페이지 목차
이 페이지에서 검색
AI 드리븐
이 페이지에 묻기
AI 드리븐 · 현재 차시와 목차 본문에서만 찾아 답합니다. 답을 지어내지 않고 해당하는 대목을 그대로 보여 주며, 여기에 없으면 없다고 알려 드립니다.
생성형 AI가 아니라 이 페이지 본문을 찾아 그대로 보여 주는 방식입니다. 외부로 나가는 요청이 없습니다.
AI · DEVELOPMENT
AI 드리븐
생성 수정
요구사항과 역할 정의부터 구현·검증·배포·운영까지, AI와 함께 개발하며 사람이 판단할 기준을 정리합니다.
26개 문서 · 1일차 · 5 / 26
4차시 · 기획 ② 범위 결정과 서비스 설계
지도 위치 : 1일차 · 기획 · 만들 범위와 화면 ↔ 서버의 약속 | 이전: 3차시 요구사항을 완료 기준으로 | 다음: 5차시 AI 역할 정의의 원리 키워드 : 최소 기능 범위(MVP), 서비스 인터페이스(API), 설계 기준
이 차시를 다 읽으면
- MVP 를 유와 종차로 정의하고, Must / Should / Could / Won't로 범위를 나눌 수 있다. 특히 "이번엔 안 함" 목록이 왜 가장 중요한지 말할 수 있다.
- API · HTTP · 메서드 · 상태 코드 를 각각 정의하고, API 표 한 줄을 코드 없이 읽을 수 있다.
- 자주 쓰는 상태 코드 여덟 개의 뜻을 말할 수 있다.
- 멱등성 을 정의하고, 같은 요청을 두 번 보냈을 때 위험한 요청을 골라낼 수 있다.
- API 요청 칸에서 서버가 정해야 할 값 (금액, 권한 등)을 찾아 설계 단계에서 지적할 수 있다.
0. 이 차시의 판별 축
| # | 축 | 왼쪽 (0) | 오른쪽 (1) | 이 축으로 갈리는 것 | 큰 축 (README 5장) |
|---|---|---|---|---|---|
| 1 | ⭐ 추상 ↔ 구상 | API 명세 (무엇을 주고받기로 약속했나) | 구현 (그 약속을 지키는 코드) | 명세와 코드가 다르면 무엇을 고치나 | ② |
| 2 | 멱등 ↔ 비멱등 | 여러 번 보내도 결과 상태가 같음 (조회, 덮어쓰기) | 보낼 때마다 상태가 바뀜 (예약 생성, 결제) | 버튼 연타 · 재전송이 위험한가 | ⑦의 파생 |
| 3 | 화면이 판정 ↔ 서버가 판정 | 화면이 보낸 값을 믿음 (조작 가능) | 서버가 직접 계산 · 확인 | 금액 · 권한을 요청에 넣어도 되나 | ②의 파생 |
| 4 | 범위 안 ↔ 범위 밖 | 이번에 만든다 | 이번엔 안 만든다 (명시) | AI가 기능을 덧붙일 때 막을 근거 | 이 차시의 축 |
이 차시가 답하는 질문은 두 가지입니다. 무엇을 만들지 않을 것인가 (축 4), 그리고 화면과 서버가 무엇을 주고받기로 약속하는가 (축 1). 앞에서 배운 인수 기준(3차시 4절)이 "무엇이 맞는 상태인가"였다면, API 명세는 그 상태를 화면과 서버 사이의 약속 으로 옮긴 것입니다.
1. 범위 결정 — MVP
1.1 정의
MVP (최소 기능 제품, Minimum Viable Product) — [출시 범위]인데, [ 서비스의 핵심 가치를 전달하는 데 꼭 필요한 기능만 담는다 ]는 점에서 원하는 기능을 모두 담은 완성판과 구별된다.
나누는 기준은 한 질문입니다. "이것 없이도 서비스의 핵심 가치가 전달되는가?"
| 구분 | 의미 | 클래스온 예 |
|---|---|---|
| 반드시 (Must) | 없으면 서비스가 아님 | 클래스 목록 · 상세, 예약, 결제, 내 예약 보기 |
| 해야 함 (Should) | 중요하지만 첫 출시엔 없어도 됨 | 예약 취소 · 환불 |
| 있으면 좋음 (Could) | 여유 있으면 | 지역 필터, 찜하기 |
| 이번엔 안 함 (Won't) | 명시적으로 제외 | 리뷰, 쿠폰, 알림톡, 운영자 정산 |
1.2 ⭐ "이번엔 안 함" 목록이 가장 중요하다
AI는 범위를 넓히는 경향이 있습니다. "예약 기능"을 시키면 쿠폰, 리뷰, 알림까지 붙이려 합니다. 범위 밖 목록이 없으면 막을 근거가 없습니다.
"이번엔 안 함" 목록을 지침 파일(2차시 2.1)에 넣어 두면, 에이전트가 범위를 벗어날 때 스스로 멈출 근거 가 생깁니다.
## 범위
- 이번엔 안 함: 리뷰, 쿠폰, 알림톡, 운영자 정산
- 위 기능이 필요해 보이면 만들지 말고 나에게 먼저 묻는다
🔍 읽는 포인트 : 두 번째 줄 "만들지 말고 묻는다"가 핵심입니다. 목록만 있으면 AI가 "필요해서 만들었습니다"라고 넘어갈 수 있습니다.
1.3 반례 — 이건 MVP가 아닙니다
| 대상 | 왜 아닌가 |
|---|---|
| 예약은 되는데 자리가 없을 때 처리가 없는 버전 | MVP는 기능 수를 줄이는 것이지 실패 시나리오를 빼는 것 이 아니다. Must 기능은 3차시의 실패 시나리오까지 완성 |
| 화면만 있고 실제로 예약이 저장되지 않는 시안 | 핵심 가치(예약)가 실제로 전달되지 않는다 . 그건 시안(6차시) |
| "일단 다 만들고 나중에 빼자" | 범위 결정을 미룬 것. AI는 만든 것을 지우기보다 덧붙이기 를 잘한다 |
2. ⭐ API와 HTTP의 기본
2.1 화면과 서버
클라이언트 (화면, 프론트엔드) — [서비스의 한쪽 끝]인데, [ 사용자의 기기(브라우저 · 휴대폰)에서 돌며 보여 주고 입력받는다 ]는 점에서 우리 쪽 컴퓨터에서 돌며 판정 · 저장하는 서버와 구별된다.
서버 (백엔드) — [서비스의 한쪽 끝]인데, [ 우리가 관리하는 컴퓨터에서 돌며 요청을 받아 판정하고 데이터를 저장한다 ]는 점에서 사용자 기기에서 도는 클라이언트와 구별된다.
API (서비스 인터페이스) — [소프트웨어 사이의 약속]인데, [ 클라이언트와 서버가 주고받을 요청 · 응답의 모양을 정한다 ]는 점에서 그 약속을 실제로 지키는 코드인 구현과 구별된다.
HTTP — [통신 규약]인데, [ 요청 하나를 보내면 응답 하나가 돌아오는 형식으로 웹에서 데이터를 주고받는다 ]는 점에서 연결을 열어 두고 계속 주고받는 방식과 구별된다.
화면(클라이언트) ──요청: POST /reservations {클래스, 날짜, 인원}──▶ 서버
화면(클라이언트) ◀──응답: 201 {예약 번호, 상태, 금액}────────────── 서버
🔍 읽는 포인트 : 오른쪽 화살표 줄의 POST /reservations(무엇을 하려는가)와 왼쪽 화살표 줄의 201(결과가 어떤가)만 보면 됩니다.
2.2 요청의 두 부분 — 메서드와 경로
경로 (Path) — [요청의 대상 표시]인데, [ 무엇에 대한 요청인지(클래스, 예약)를 주소로 나타낸다 ]는 점에서 무엇을 하려는지를 나타내는 메서드와 구별된다.
HTTP 메서드 — [요청의 종류 표시]인데, [ 같은 대상에 대해 무엇을 하려는지(조회 · 생성 · 변경 · 삭제)를 나타낸다 ]는 점에서 대상을 나타내는 경로와 구별된다.
| 메서드 | 하는 일 | 예 |
|---|---|---|
| GET | 조회 (아무것도 바꾸지 않음) | GET /classes — 클래스 목록 보기 |
| POST | 새로 만들기 · 동작 실행 | POST /reservations — 예약 만들기 |
| PUT | 통째로 덮어쓰기 | PUT /classes/12 — 클래스 정보 전체 교체 |
| PATCH | 일부만 고치기 | PATCH /classes/12 — 정원만 바꾸기 |
| DELETE | 지우기 | DELETE /classes/12 |
2.3 응답의 두 부분 — 상태 코드와 본문
상태 코드 — [응답의 일부]인데, [ 결과의 종류를 세 자리 숫자로 알린다 ]는 점에서 실제 데이터를 담은 응답 본문과 구별된다.
첫 자리가 큰 갈래입니다. 2로 시작하면 성공, 4로 시작하면 요청한 쪽 문제, 5로 시작하면 서버 쪽 문제 입니다. 이 과정에서는 아래 여덟 개면 충분합니다.
| 코드 | 뜻 | 클래스온 예 |
|---|---|---|
| 200 | 성공 | 목록 조회 성공 |
| 201 | 성공, 새로 만들어짐 | 예약 생성됨 |
| 400 | 보낸 값이 잘못됨 | 인원이 0명 |
| 401 | 로그인 필요 | 로그인 안 하고 예약 |
| 403 | 로그인했지만 권한 없음 | 남의 예약 취소 시도 |
| 404 | 없음 | 없는 클래스 번호 |
| 409 | 충돌 (현재 상태와 맞지 않음) | 자리 없음, 중복 예약 |
| 500 | 서버 내부 오류 (보통 버그) | — 이게 보이면 고쳐야 함 |
JSON — [데이터 표기 형식]인데, [ { "이름": 값 } 모양으로 사람도 읽고 프로그램도 읽을 수 있다 ]는 점에서 사람만 읽는 자유 문장과 구별된다. 요청과 응답의 본문은 대부분 JSON입니다.
2.4 API 명세 한 줄에 들어가는 것
| 항목 | 내용 | 예 |
|---|---|---|
| 메서드 + 경로 | 무엇에 무엇을 하나 | POST /reservations |
| 요청 | 보내는 데이터 | { "classId": 12, "date": "2026-11-01", "headcount": 1 } |
| 응답 | 받는 데이터 | { "id": 345, "status": "PENDING_PAYMENT", "amount": 55000 } |
| 상태 코드 | 결과 종류 | 201, 400, 401, 409 |
| 에러 형식 | 실패 시 모양 | { "error": { "code": "SOLD_OUT", "message": "..." } } |
| 인증 | 로그인 필요 여부 | 필요 |
⭐ API 표는 코드를 몰라도 읽을 수 있는 서비스의 설계도입니다. 코드는 맡기더라도 API 표는 내가 직접 이해하고 승인하는 마지막 층 으로 삼습니다. 이 표만 이해해도 화면과 서버 사이에서 무엇이 오가는지 전부 파악할 수 있습니다.
3. 설계 기준
3.1 여섯 가지 규칙
AI도 이 규칙을 알지만, 명시하지 않으면 일관되게 지키지 않습니다.
| # | 규칙 | ⭕ / ❌ |
|---|---|---|
| 1 | 경로는 명사, 동작은 메서드로 | ⭕ POST /reservations ❌ POST /createReservation |
| 2 | 에러 형식은 하나로 통일 | 화면 쪽이 한 가지 방식으로만 처리하면 되도록 |
| 3 | 상태 코드를 뜻대로 | ❌ 실패를 200 + { success: false }로 돌려주기 — 성공 코드에 실패를 숨기면 자동 검사와 화면이 모두 속는다 |
| 4 | 서버가 판정할 값은 받지 않기 | 3.2절 |
| 5 | 목록은 페이지 단위로 | GET /classes?page=1&size=20 |
| 6 | 같은 요청을 두 번 보내도 안전하게 | 3.3절 |
3.2 서버가 판정할 값은 받지 않는다
화면은 사용자의 기기에서 돌기 때문에 사용자가 조작할 수 있습니다. 예약 요청에 금액을 넣으면, 누군가 55000을 100으로 바꿔 보낼 수 있습니다. 그래서 금액은 서버가 DB의 가격으로 직접 계산 합니다(0절 축 3).
⭐ API 표에서 코드 없이 찾아낼 수 있는 위험 입니다. 요청 칸에 아래 같은 값이 들어 있으면 설계 단계에서 바로 지적하세요.
| 요청에 있으면 위험한 값 | 왜 |
|---|---|
amount, price | 금액은 서버가 계산 |
userId | 누가 보냈는지는 서버가 로그인 정보로 판단 |
role, isAdmin | 권한은 서버가 판단 |
remaining (남은 자리) | 재고는 서버가 DB에서 확인 |
앞으로 다시 만납니다 — 10 · 11차시에서 "화면이 판정 ↔ 서버가 판정" 축을 본격적으로 다루고, 16차시에서 결제 금액 위변조를 실제로 막습니다.
3.3 ⭐ 멱등성 — 같은 요청을 두 번 보내면?
멱등성 (Idempotency) — [요청의 성질]인데, [ 같은 요청을 여러 번 보내도 결과 상태가 한 번 보낸 것과 같다 ]는 점에서 보낼 때마다 상태가 바뀌는 비멱등 요청과 구별된다.
| 요청 | 두 번 보내면 | 멱등? |
|---|---|---|
GET /classes | 아무것도 안 바뀜 | ⭕ 멱등 |
PUT /classes/12 (정원 6으로 덮어쓰기) | 두 번 해도 정원 6 | ⭕ 멱등 |
DELETE /classes/12 | 첫 번째에 지워지고, 두 번째엔 이미 없음 | ⭕ 멱등 (응답은 달라도 결과 상태 는 같음) |
POST /reservations | 예약이 두 개 생김 | ❌ 비멱등 |
POST /payments/confirm | 결제가 두 번 될 수 있음 | ❌ 비멱등 |
⚠️ 멱등은 "응답이 같다"가 아니라 "결과 상태가 같다" 입니다. 위 DELETE처럼 두 번째 응답은 404일 수 있습니다.
같은 요청은 생각보다 자주 두 번 갑니다. 사용자가 결제 버튼을 연타하거나, 네트워크가 끊겨 화면이 자동으로 다시 보내거나, 결제사가 같은 알림을 두 번 보내는 경우입니다. 그래서 비멱등 요청 중 중복이 치명적인 곳 (예약, 결제)은 설계 단계에서 표시해 둡니다.
앞으로 다시 만납니다 — 16차시에서 결제 요청에 같은 요청임을 알아보는 표시(멱등 키) 를 붙여 두 번 와도 한 번만 처리되게 만듭니다.
4. 명세를 단일 기준으로
4.1 저장과 규칙
API 명세는 docs/api.md(사람이 읽기 쉬움)나 OpenAPI 형식의 openapi.yaml(API 명세를 적는 표준 형식, 도구가 읽기 쉬움)로 저장합니다. 그리고 지침 파일에 이렇게 적습니다.
API는 docs/api.md가 유일한 기준이다. 구현이 명세와 다르면 구현을 고친다.
명세를 바꿔야 하면 먼저 사람에게 묻는다.
docs/api.md를 바꾸면 무엇이 왜 바뀌었는지 먼저 알린다.
🔍 읽는 포인트 : 첫 줄의 "구현을 고친다"가 축 1의 방향입니다. 약속(추상)이 기준이고, 코드(구상)가 따라갑니다. 셋째 줄은 AI가 구현 중에 슬그머니 계약을 바꾸는 일 을 막습니다.
⭐ 프론트엔드와 백엔드를 서로 다른 에이전트가 만들면, 둘이 같은 약속을 보고 있어야 연결됩니다(11차시). 명세 하나를 두 역할과 테스트가 함께 봅니다.
| 누가 | 명세를 어떻게 쓰나 |
|---|---|
| 백엔드 역할 | 이 모양대로 응답을 만든다 |
| 프론트엔드 역할 | 이 모양을 믿고 화면을 만든다 |
| 테스트 · 검증 역할 | 이 모양과 실제 응답이 같은지 확인한다 |
4.2 반례 — 이건 API 명세가 아닙니다
| 대상 | 왜 아닌가 |
|---|---|
| 코드를 다 짠 뒤 코드에서 뽑아낸 문서 | 현재 상태의 기록 일 뿐, 먼저 정한 약속이 아니다. 코드가 틀리면 문서도 같이 틀린다 |
| "예약 API 하나 있음" | 요청 · 응답 · 상태 코드가 없으면 양쪽이 다른 모양을 상상 한다 |
💡 비유는 마지막에 — API 명세는 콘센트 규격입니다. 규격(약속)이 정해져 있으면 어느 회사가 플러그(구현)를 만들어도 꽂힙니다.
4.3 클래스온에 적용하면
| 메서드 | 경로 | 설명 | 인증 | 멱등? |
|---|---|---|---|---|
| GET | /classes | 클래스 목록 (날짜, 페이지) | 불필요 | ⭕ |
| GET | /classes/{id} | 클래스 상세 + 날짜별 남은 자리 | 불필요 | ⭕ |
| POST | /reservations | 예약 생성 (결제 대기 상태) | 필요 | ❌ 연타 주의 |
| GET | /me/reservations | 내 예약 목록 | 필요 | ⭕ |
| POST | /payments/confirm | 결제 승인 (16차시) | 필요 | ❌ 중복 치명적 |
| POST | /reservations/{id}/cancel | 예약 취소 (Should) | 필요 | 설계에 따라 (이미 취소된 예약이면 그대로 두게) |
5. 실습 — 맡기고 검수하기
지시
docs/requirements.md를 근거로 두 문서를 만들어줘.
1. docs/scope.md: Must / Should / Could / Won't 표. Won't는 최소 4개, 각각 빼는 이유 한 줄.
2. docs/api.md: [메서드 | 경로 | 요청 본문 | 응답 본문 | 상태 코드 | 인증 | 멱등 여부] 표.
에러 형식은 { "error": { "code", "message" } } 하나로 통일.
규칙: 요청 본문에 금액 · 사용자 ID · 권한 · 남은 자리 값을 넣지 말 것.
비멱등 요청 중 중복되면 위험한 것은 표에 [중복 주의]로 표시할 것.
그리고 CLAUDE.md에 "Won't 목록"과 "docs/api.md가 유일한 기준" 규칙을 추가해줘 (추가 전 내용을 보여주고 승인받을 것).
보고: 두 문서의 원문 + 각 상태 코드를 어떤 실패 시나리오(requirements.md)에 대응시켰는지 표.
받을 증거
docs/scope.md,docs/api.md원문- 상태 코드 ↔ 3차시 실패 시나리오 대응표
내가 직접 확인할 것
| 볼 것 | 이걸로 아는 것 / 왜 내가 보는가 |
|---|---|
API 표의 요청 본문 칸 을 한 줄씩 훑어 amount, price, userId, role, isAdmin, remaining 찾기 | 서버가 판정할 값을 화면에서 받게 설계됐는지. 코드 없이 잡을 수 있는 가장 큰 위험 (3.2) |
| 3차시 실패 시나리오마다 대응하는 상태 코드 가 있는지 | 실패 경로가 API 약속에 빠지지 않았는지 |
성공 코드(200)에 실패가 숨어 있는지 (success: false 같은 글자) | 상태 코드를 뜻대로 쓰는지 (3.1 규칙 3) |
POST /reservations, POST /payments/confirm에 [중복 주의] 가 붙었는지 | 비멱등 요청의 위험을 설계 단계에서 표시했는지 (3.3) |
| Won't 목록의 각 항목에 내가 동의하는가 | 범위는 내가 정하는 사업 결정 (README 9.2) |
부록 A. 스스로 확인하기
| # | 질문 | 답이 있는 곳 |
|---|---|---|
| 1 | MVP를 유와 종차로 정의하면? | 1.1 |
| 2 | 클래스온에서 "리뷰 작성"을 이번 범위에서 빼야 하는 이유는? | 1.1, 1.2 |
| 3 | "이번엔 안 함" 목록이 가장 중요한 이유는? | 1.2 |
| 4 | 실패 시나리오를 뺀 버전이 MVP가 아닌 이유는? | 1.3 |
| 5 | 메서드와 경로의 종차는? | 2.2 |
| 6 | 401과 403의 차이는? 409는 언제 쓰나? | 2.3 |
| 7 | POST /reservations 요청 본문에 금액을 넣으면 안 되는 이유는? | 3.2 |
| 8 | 실패를 200 응답으로 돌려주면 어떤 문제가 생기나? | 3.1 |
| 9 | 멱등성을 정의하고, DELETE가 두 번째에 404를 돌려줘도 멱등인 이유는? | 3.3 |
| 10 | API 명세가 백엔드 · 프론트엔드 · 테스트 역할에게 각각 무슨 역할을 하나? | 4.1 |
부록 B. 자주 하는 실수
| 실수 | 바로잡기 |
|---|---|
| 화면부터 만들고 API는 필요할 때 맞춰서 만든다 | ❌ 프론트 · 백엔드 에이전트가 각자 다른 모양을 상상합니다 (4.1) |
| 화면이 금액 · 권한 · 재고 값을 보내게 설계한다 | ❌ 서버가 판정할 값은 받지 않습니다 (3.2) |
| "이번엔 안 함" 목록을 적지 않는다 | ⚠️ AI가 덧붙일 때 막을 근거가 없습니다 (1.2) |
실패를 200 + success: false로 돌려준다 | ❌ 상태 코드를 뜻대로 (3.1) |
| "멱등 = 응답이 같다" | ❌ 결과 상태 가 같은 것입니다 (3.3) |
| 명세를 고쳤는데 지침 파일 · 다른 문서에 반영하지 않는다 | ⭕ 명세 변경은 먼저 알리게 규칙으로 (4.1) |
| MVP를 "대충 만든 버전"으로 이해한다 | ❌ 기능 수를 줄일 뿐, Must는 실패 경로까지 완성 (1.3) |
부록 C. NotebookLM 복습 프롬프트
이 4차시 노트만 근거로 6문제를 내줘. 코드를 모르는 사람 기준으로.
"Won't 목록의 역할", "메서드 · 경로 · 상태 코드 읽기", "서버가 판정할 값", "멱등성"은 반드시 포함해줘.
API 표 한 줄을 주고 위험한 요청 값을 내가 찾아보게 하는 문제도 1개 넣어줘.
답은 내가 답한 다음에 채점하고, 틀린 이유를 노트의 절 번호를 근거로 설명해줘.
LangTailor