🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
786 lines
16 KiB
Markdown
786 lines
16 KiB
Markdown
# appkit.design
|
|
|
|
**개발 준비 - API, ERD, 기술 스펙 설계**
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
**This is Step 7 of the logical thinking 7-step workflow**:
|
|
|
|
```
|
|
논리적 사고 7단계:
|
|
1. /appkit.new → 아이디어 스케치 (어떤 서비스인지?)
|
|
2. /appkit.spec → 기능 구체화 (뭐가 필요할까? 누가 쓸까?)
|
|
3. /appkit.customer → 고객 스토리 (고객의 하루, 고민, 해결)
|
|
4. /appkit.sales → 세일즈 랜딩 구성 (어떻게 설득할까?)
|
|
5. /appkit.mvp → MVP 범위 정하기 (최소한으로 검증하려면?)
|
|
6. /appkit.merge → 기획 정돈 (흩어진 기획 통합)
|
|
7. /appkit.design → 개발 준비 (API, ERD, 기술 스펙) ← YOU ARE HERE
|
|
```
|
|
|
|
## Purpose
|
|
|
|
merge에서 정돈된 기획을 기반으로, 실제 개발에 필요한 **기술 스펙**을 생성합니다.
|
|
기획 레벨(merge)과 구현 레벨(개발) 사이의 다리 역할을 합니다.
|
|
|
|
**핵심 질문**: "개발자에게 뭘 전달해야 하나? 어떻게 만들까?"
|
|
|
|
---
|
|
|
|
## When to Use
|
|
|
|
- `/appkit.merge`로 기획을 정돈한 후 (Step 6 완료 후)
|
|
- 개발 시작 직전
|
|
- 기술 스펙이 필요할 때
|
|
- ERD, API 설계가 필요할 때
|
|
|
|
---
|
|
|
|
## Usage
|
|
|
|
```bash
|
|
/appkit.design
|
|
/appkit.design "persona 도메인 집중"
|
|
/appkit.design "API 우선"
|
|
```
|
|
|
|
---
|
|
|
|
## What I'll Do
|
|
|
|
### 1. 소스 문서 읽기
|
|
|
|
**읽을 파일들**:
|
|
- `docs/appkit/merge/concept-map.md` (통합 컨셉)
|
|
- `docs/appkit/merge/consolidated-specs.md` (통합 스펙)
|
|
- `docs/appkit/merge/journey-feature-map.md` (기능 매핑)
|
|
- `docs/appkit/mvp-scope.md` (MVP 범위)
|
|
|
|
### 2. 데이터 엔티티 설계 (ERD)
|
|
|
|
**Output**: `docs/appkit/design/entities.md`
|
|
|
|
```markdown
|
|
# Data Entity Design (ERD)
|
|
|
|
*생성 기준: concept-map.md, consolidated-specs.md*
|
|
*생성일: 2025-11-20*
|
|
|
|
---
|
|
|
|
## Entity Relationship Diagram
|
|
|
|
```mermaid
|
|
erDiagram
|
|
Persona ||--o{ Content : generates
|
|
Content ||--|| Post : becomes
|
|
Schedule ||--o{ Post : manages
|
|
|
|
Persona {
|
|
int id PK
|
|
string name
|
|
int age
|
|
string personality
|
|
string tone
|
|
string language
|
|
json style_rules
|
|
datetime created_at
|
|
}
|
|
|
|
Content {
|
|
int id PK
|
|
int persona_id FK
|
|
string topic
|
|
string image_url
|
|
text caption
|
|
json hashtags
|
|
enum status
|
|
datetime generated_at
|
|
}
|
|
|
|
Post {
|
|
int id PK
|
|
int content_id FK
|
|
string platform
|
|
datetime scheduled_at
|
|
datetime posted_at
|
|
enum status
|
|
}
|
|
|
|
Schedule {
|
|
int id PK
|
|
time execution_time
|
|
bool is_active
|
|
json target_personas
|
|
}
|
|
```
|
|
```
|
|
|
|
---
|
|
|
|
## Entity Details
|
|
|
|
### Entity: Persona
|
|
|
|
**Purpose**: 캐릭터별 페르소나 정보 저장
|
|
|
|
**Table Name**: `personas`
|
|
|
|
**Fields**:
|
|
|
|
| Field | Type | Constraints | Description |
|
|
|-------|------|-------------|-------------|
|
|
| id | INT | PK, AUTO_INCREMENT | 페르소나 고유 ID |
|
|
| name | VARCHAR(100) | NOT NULL | 캐릭터 이름 |
|
|
| age | INT | NOT NULL | 캐릭터 나이 |
|
|
| personality | TEXT | NOT NULL | 성격 설명 |
|
|
| tone | VARCHAR(50) | NOT NULL | 말투 (밝은/전문가/친근한) |
|
|
| language | VARCHAR(10) | NOT NULL | 언어 (ko/en/ja) |
|
|
| style_rules | JSON | NULL | 스타일 규칙 (이모티콘, 반말/존댓말) |
|
|
| created_at | DATETIME | NOT NULL, DEFAULT NOW() | 생성 시간 |
|
|
|
|
**Relationships**:
|
|
- `Persona.id` → `Content.persona_id` (1:N)
|
|
|
|
**Business Rules**:
|
|
- 한 페르소나는 여러 콘텐츠 생성 가능
|
|
- 페르소나 삭제 시 생성된 콘텐츠는 보존 (FK: RESTRICT)
|
|
|
|
**Sample Data**:
|
|
```json
|
|
{
|
|
"id": 1,
|
|
"name": "밝은 20대 여성",
|
|
"age": 25,
|
|
"personality": "긍정적이고 친근한 성격",
|
|
"tone": "밝은",
|
|
"language": "ko",
|
|
"style_rules": {
|
|
"emoji_frequency": "high",
|
|
"formality": "casual",
|
|
"hashtag_style": "trendy"
|
|
},
|
|
"created_at": "2025-01-01T10:00:00Z"
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
### Entity: Content
|
|
|
|
**Purpose**: AI가 생성한 콘텐츠 저장
|
|
|
|
**Table Name**: `contents`
|
|
|
|
**Fields**:
|
|
|
|
| Field | Type | Constraints | Description |
|
|
|-------|------|-------------|-------------|
|
|
| id | INT | PK, AUTO_INCREMENT | 콘텐츠 고유 ID |
|
|
| persona_id | INT | FK → personas.id, NOT NULL | 생성한 페르소나 |
|
|
| topic | VARCHAR(200) | NOT NULL | 주제 |
|
|
| image_url | VARCHAR(500) | NOT NULL | 이미지 URL (Midjourney) |
|
|
| caption | TEXT | NOT NULL | 캡션 (GPT 생성) |
|
|
| hashtags | JSON | NULL | 해시태그 배열 |
|
|
| status | ENUM | NOT NULL | draft, approved, posted |
|
|
| generated_at | DATETIME | NOT NULL, DEFAULT NOW() | 생성 시간 |
|
|
|
|
**Enums**:
|
|
- `status`: `draft` (생성됨), `approved` (검토 완료), `posted` (포스팅됨)
|
|
|
|
**Relationships**:
|
|
- `Content.persona_id` → `Persona.id` (N:1)
|
|
- `Content.id` → `Post.content_id` (1:1)
|
|
|
|
**Business Rules**:
|
|
- 하나의 콘텐츠는 하나의 포스트로 변환
|
|
- 캡션 길이: 최소 50자, 최대 2200자 (Instagram 제한)
|
|
|
|
---
|
|
|
|
### Entity: Post
|
|
|
|
**Purpose**: 실제 포스팅 기록
|
|
|
|
**Table Name**: `posts`
|
|
|
|
**Fields**:
|
|
|
|
| Field | Type | Constraints | Description |
|
|
|-------|------|-------------|-------------|
|
|
| id | INT | PK, AUTO_INCREMENT | 포스트 고유 ID |
|
|
| content_id | INT | FK → contents.id, UK, NOT NULL | 연결된 콘텐츠 |
|
|
| platform | VARCHAR(50) | NOT NULL | instagram, twitter, etc |
|
|
| scheduled_at | DATETIME | NOT NULL | 예약 시간 |
|
|
| posted_at | DATETIME | NULL | 실제 포스팅 시간 |
|
|
| status | ENUM | NOT NULL | pending, posted, failed |
|
|
|
|
**Enums**:
|
|
- `status`: `pending` (대기), `posted` (완료), `failed` (실패)
|
|
|
|
**Relationships**:
|
|
- `Post.content_id` → `Content.id` (1:1)
|
|
|
|
**Business Rules**:
|
|
- 하나의 콘텐츠는 하나의 포스트
|
|
- 포스팅 실패 시 재시도 로직 필요
|
|
|
|
---
|
|
|
|
## Summary
|
|
|
|
- **Total Entities**: 4 (Persona, Content, Post, Schedule)
|
|
- **Total Relationships**: 3 (1:N, 1:1)
|
|
- **Foreign Keys**: 3
|
|
|
|
**Entity Dependencies** (구현 순서):
|
|
1. **No dependencies**: Persona, Schedule (먼저 구현)
|
|
2. **Depends on 1**: Content (needs Persona)
|
|
3. **Depends on 2**: Post (needs Content)
|
|
```
|
|
|
|
### 3. API 엔드포인트 설계
|
|
|
|
**Output**: `docs/appkit/design/apis.md`
|
|
|
|
```markdown
|
|
# API Endpoint Design
|
|
|
|
*생성 기준: entities.md, consolidated-specs.md*
|
|
*API Style: RESTful*
|
|
*Base URL: `/api/v1`*
|
|
|
|
---
|
|
|
|
## 1. Persona APIs
|
|
|
|
### 1.1 Create Persona
|
|
|
|
**Endpoint**: `POST /personas`
|
|
|
|
**Description**: 새로운 페르소나 생성
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"name": "밝은 20대 여성",
|
|
"age": 25,
|
|
"personality": "긍정적이고 친근한 성격",
|
|
"tone": "밝은",
|
|
"language": "ko",
|
|
"style_rules": {
|
|
"emoji_frequency": "high",
|
|
"formality": "casual"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Success Response** (201 Created):
|
|
```json
|
|
{
|
|
"persona": {
|
|
"id": 1,
|
|
"name": "밝은 20대 여성",
|
|
"age": 25,
|
|
"tone": "밝은",
|
|
"created_at": "2025-01-01T10:00:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Error Responses**:
|
|
- 400 Bad Request: Validation failed
|
|
|
|
**Related Spec**: 001-persona/spec.md
|
|
**Related Entity**: Persona
|
|
|
|
---
|
|
|
|
### 1.2 List Personas
|
|
|
|
**Endpoint**: `GET /personas`
|
|
|
|
**Description**: 모든 페르소나 조회
|
|
|
|
**Success Response** (200 OK):
|
|
```json
|
|
{
|
|
"personas": [
|
|
{
|
|
"id": 1,
|
|
"name": "밝은 20대 여성",
|
|
"age": 25,
|
|
"tone": "밝은"
|
|
},
|
|
{
|
|
"id": 2,
|
|
"name": "전문가 30대 남성",
|
|
"age": 32,
|
|
"tone": "전문가"
|
|
}
|
|
],
|
|
"total": 2
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 2. Content APIs
|
|
|
|
### 2.1 Generate Content
|
|
|
|
**Endpoint**: `POST /contents/generate`
|
|
|
|
**Description**: AI로 콘텐츠 자동 생성
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"persona_id": 1,
|
|
"topic": "오늘의 운동 루틴",
|
|
"auto_post": false
|
|
}
|
|
```
|
|
|
|
**Success Response** (201 Created):
|
|
```json
|
|
{
|
|
"content": {
|
|
"id": 101,
|
|
"persona_id": 1,
|
|
"topic": "오늘의 운동 루틴",
|
|
"image_url": "https://midjourney.com/...",
|
|
"caption": "오늘도 열심히 운동했어요! 💪...",
|
|
"hashtags": ["운동", "헬스", "루틴"],
|
|
"status": "draft",
|
|
"generated_at": "2025-01-01T07:00:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Business Logic**:
|
|
1. persona_id로 페르소나 정보 조회
|
|
2. Midjourney API 호출 (이미지 생성)
|
|
3. GPT API 호출 (캡션 생성, 페르소나 톤 반영)
|
|
4. 생성된 콘텐츠 DB 저장 (status: draft)
|
|
5. auto_post = true면 자동 포스팅 예약
|
|
|
|
**Error Responses**:
|
|
- 404 Not Found: Persona not found
|
|
- 502 Bad Gateway: Midjourney/GPT API 실패
|
|
- 503 Service Unavailable: API rate limit 초과
|
|
|
|
**Related Spec**: 002-content/spec.md
|
|
**Related Entity**: Content, Persona
|
|
|
|
---
|
|
|
|
### 2.2 List Contents
|
|
|
|
**Endpoint**: `GET /contents`
|
|
|
|
**Query Parameters**:
|
|
```
|
|
?persona_id=1 // Filter by persona
|
|
&status=draft // Filter by status
|
|
&date=2025-01-01 // Filter by generation date
|
|
&limit=20
|
|
&page=1
|
|
```
|
|
|
|
**Success Response** (200 OK):
|
|
```json
|
|
{
|
|
"contents": [
|
|
{
|
|
"id": 101,
|
|
"persona_id": 1,
|
|
"topic": "오늘의 운동 루틴",
|
|
"image_url": "https://...",
|
|
"status": "draft",
|
|
"generated_at": "2025-01-01T07:00:00Z"
|
|
}
|
|
],
|
|
"pagination": {
|
|
"total": 45,
|
|
"page": 1,
|
|
"limit": 20
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 3. Schedule APIs
|
|
|
|
### 3.1 Create Schedule
|
|
|
|
**Endpoint**: `POST /schedules`
|
|
|
|
**Description**: 자동 생성 스케줄 등록
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"execution_time": "07:00",
|
|
"target_personas": [1, 2, 3],
|
|
"is_active": true
|
|
}
|
|
```
|
|
|
|
**Success Response** (201 Created):
|
|
```json
|
|
{
|
|
"schedule": {
|
|
"id": 1,
|
|
"execution_time": "07:00",
|
|
"target_personas": [1, 2, 3],
|
|
"is_active": true
|
|
}
|
|
}
|
|
```
|
|
|
|
**Business Logic**:
|
|
- Cron job 생성 (매일 07:00 실행)
|
|
- 실행 시 target_personas의 각 페르소나로 콘텐츠 생성
|
|
- 생성 후 자동 포스팅
|
|
|
|
**Related Spec**: 003-schedule/spec.md
|
|
**Related Entity**: Schedule
|
|
|
|
---
|
|
|
|
## 4. Post APIs
|
|
|
|
### 4.1 Create Post
|
|
|
|
**Endpoint**: `POST /posts`
|
|
|
|
**Description**: 콘텐츠를 포스팅으로 예약
|
|
|
|
**Request Body**:
|
|
```json
|
|
{
|
|
"content_id": 101,
|
|
"platform": "instagram",
|
|
"scheduled_at": "2025-01-01T12:00:00Z"
|
|
}
|
|
```
|
|
|
|
**Success Response** (201 Created):
|
|
```json
|
|
{
|
|
"post": {
|
|
"id": 201,
|
|
"content_id": 101,
|
|
"platform": "instagram",
|
|
"scheduled_at": "2025-01-01T12:00:00Z",
|
|
"status": "pending"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Business Logic**:
|
|
1. content_id로 콘텐츠 조회
|
|
2. 포스트 생성 (status: pending)
|
|
3. scheduled_at 시간에 Instagram API 호출
|
|
4. 성공 시 status = posted, 실패 시 status = failed
|
|
|
|
**Related Spec**: 003-schedule/spec.md (포스팅)
|
|
**Related Entity**: Post, Content
|
|
|
|
---
|
|
|
|
## API Summary
|
|
|
|
| Domain | Endpoints | Description |
|
|
|--------|-----------|-------------|
|
|
| Persona | 3 (create, list, update) | 페르소나 관리 |
|
|
| Content | 2 (generate, list) | 콘텐츠 생성 |
|
|
| Schedule | 2 (create, list) | 스케줄 관리 |
|
|
| Post | 2 (create, list) | 포스팅 관리 |
|
|
|
|
**Total Endpoints**: 9
|
|
|
|
---
|
|
|
|
## Error Response Format
|
|
|
|
**Standard Error Response**:
|
|
```json
|
|
{
|
|
"error": {
|
|
"code": "API_RATE_LIMIT",
|
|
"message": "Midjourney API rate limit exceeded",
|
|
"details": {
|
|
"limit": 50,
|
|
"current": 51,
|
|
"reset_at": "2025-01-01T08:00:00Z"
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
**Error Codes**:
|
|
- `VALIDATION_ERROR`: 입력 검증 실패
|
|
- `API_RATE_LIMIT`: API 제한 초과
|
|
- `GENERATION_FAILED`: 콘텐츠 생성 실패
|
|
- `NOT_FOUND`: 리소스 없음
|
|
```
|
|
|
|
### 4. 기술 정책 정의
|
|
|
|
**Output**: `docs/appkit/design/tech-policies.md`
|
|
|
|
```markdown
|
|
# Technical Policies
|
|
|
|
*기술 구현 관련 정책*
|
|
|
|
---
|
|
|
|
## API Rate Limiting
|
|
|
|
### Midjourney API
|
|
- **Limit**: 시간당 50회
|
|
- **동시 처리**: 최대 3개
|
|
- **초과 시**: 429 에러, 다음 시간까지 대기
|
|
- **Queue**: FIFO 방식
|
|
|
|
### OpenAI GPT-4 API
|
|
- **Limit**: 분당 60회
|
|
- **토큰**: 일 500,000 제한
|
|
- **초과 시**: 429 에러
|
|
- **Retry**: Exponential backoff (1s, 2s, 4s)
|
|
|
|
### Instagram Graph API
|
|
- **Limit**: 하루 200개 포스트
|
|
- **시간당**: 25회
|
|
- **초과 시**: 403 에러
|
|
|
|
**구현 방안**:
|
|
- Rate Limiter 모듈 구현
|
|
- 우선순위 큐 시스템
|
|
- API 호출 로그 기록
|
|
|
|
---
|
|
|
|
## Error Handling
|
|
|
|
### 재시도 정책
|
|
|
|
**API 실패**:
|
|
- 재시도 횟수: 3회
|
|
- 방식: Exponential backoff
|
|
- 대기 시간: 1s, 2s, 4s
|
|
|
|
**생성 실패**:
|
|
- 재시도 횟수: 2회
|
|
- 방식: 즉시 재시도
|
|
- 실패 시: 에러 로그 기록, 알림
|
|
|
|
**품질 불량**:
|
|
- 판단 기준: 이미지 해상도 < 1080x1080
|
|
- 처리: 자동 재생성 (1회)
|
|
|
|
### 로깅
|
|
|
|
**로그 종류**:
|
|
- `error.log`: 모든 에러
|
|
- `api-calls.log`: API 호출 기록
|
|
- `generation.log`: 콘텐츠 생성 기록
|
|
|
|
**로그 레벨**:
|
|
- ERROR: 시스템 오류
|
|
- WARN: API 제한 근접
|
|
- INFO: 정상 실행
|
|
|
|
---
|
|
|
|
## Content Safety
|
|
|
|
### 브랜드 안전성
|
|
- 성인 콘텐츠: GPT moderation API로 자동 차단
|
|
- 폭력/혐오: 필터 적용
|
|
- 저작권: 학습 데이터 외 참조 금지
|
|
|
|
### 품질 검증
|
|
- 이미지: 최소 1080x1080
|
|
- 캡션: 최소 50자, 최대 2200자
|
|
- 해시태그: 5-30개
|
|
|
|
---
|
|
|
|
## Data Management
|
|
|
|
### 저장 위치
|
|
- 페르소나: Database (personas table)
|
|
- 콘텐츠: Database (contents table)
|
|
- 이미지: S3 (Midjourney URL 저장)
|
|
- 로그: `logs/` directory
|
|
|
|
### 백업
|
|
- DB 백업: 일 1회 (자정)
|
|
- S3 백업: 자동 (versioning)
|
|
- 로그 보존: 90일
|
|
```
|
|
|
|
### 5. 화면-API 매핑
|
|
|
|
**Output**: `docs/appkit/design/screen-api-map.md`
|
|
|
|
```markdown
|
|
# Screen to API Mapping
|
|
|
|
*UI 화면과 API 호출 매핑*
|
|
|
|
---
|
|
|
|
## Flow: 콘텐츠 자동 생성
|
|
|
|
### Screen 1: 페르소나 설정
|
|
|
|
**User Actions**:
|
|
- 페르소나 목록 조회
|
|
- 새 페르소나 생성
|
|
|
|
**API Calls**:
|
|
```
|
|
1. GET /personas
|
|
→ Returns: 페르소나 리스트
|
|
|
|
2. (On create) POST /personas
|
|
→ Returns: 생성된 페르소나
|
|
```
|
|
|
|
---
|
|
|
|
### Screen 2: 스케줄 설정
|
|
|
|
**User Actions**:
|
|
- 스케줄 등록
|
|
- 실행 시간 설정
|
|
- 대상 페르소나 선택
|
|
|
|
**API Calls**:
|
|
```
|
|
1. GET /personas
|
|
→ Returns: 선택 가능한 페르소나
|
|
|
|
2. (On save) POST /schedules
|
|
→ Returns: 생성된 스케줄
|
|
```
|
|
|
|
---
|
|
|
|
### Screen 3: 콘텐츠 확인
|
|
|
|
**User Actions**:
|
|
- 생성된 콘텐츠 조회
|
|
- 승인/거부
|
|
|
|
**API Calls**:
|
|
```
|
|
1. GET /contents?status=draft
|
|
→ Returns: Draft 콘텐츠 목록
|
|
|
|
2. (On approve) PATCH /contents/{id}
|
|
→ Body: { "status": "approved" }
|
|
→ Returns: 업데이트된 콘텐츠
|
|
```
|
|
|
|
---
|
|
|
|
## Complete Sequence Diagram
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
actor User
|
|
participant UI
|
|
participant API
|
|
participant Midjourney
|
|
participant GPT
|
|
participant Instagram
|
|
|
|
User->>UI: 스케줄 등록
|
|
UI->>API: POST /schedules
|
|
API-->>UI: Schedule created
|
|
|
|
Note over API: 매일 07:00 Cron 실행
|
|
|
|
API->>API: GET /personas (target)
|
|
loop Each Persona
|
|
API->>Midjourney: Generate Image
|
|
Midjourney-->>API: Image URL
|
|
API->>GPT: Generate Caption
|
|
GPT-->>API: Caption Text
|
|
API->>API: Save Content (draft)
|
|
end
|
|
|
|
User->>UI: 콘텐츠 확인
|
|
UI->>API: GET /contents?status=draft
|
|
API-->>UI: Content List
|
|
|
|
User->>UI: 승인
|
|
UI->>API: PATCH /contents/{id}
|
|
API->>Instagram: Post Content
|
|
Instagram-->>API: Success
|
|
API-->>UI: Posted
|
|
```
|
|
```
|
|
|
|
---
|
|
|
|
## Output Files
|
|
|
|
### 생성될 파일들:
|
|
|
|
```
|
|
docs/appkit/design/
|
|
├── entities.md # ERD 및 데이터 모델
|
|
├── apis.md # API 엔드포인트 설계
|
|
├── tech-policies.md # 기술 정책
|
|
└── screen-api-map.md # 화면-API 매핑
|
|
```
|
|
|
|
---
|
|
|
|
## Integration Points
|
|
|
|
### 다른 명령어와의 연계:
|
|
|
|
- **From `/appkit.merge`**: concept-map.md 사용
|
|
- **To 개발팀**: 설계 문서 전달
|
|
- **To `/appkit.verify`**: 설계 완성도 체크 (향후)
|
|
|
|
---
|
|
|
|
## Key Principles
|
|
|
|
### 설계 원칙:
|
|
|
|
1. **Planning only, no code**: 설계 문서만 생성, 코드 작성 안 함
|
|
2. **Entity-first approach**: 데이터 모델부터 설계
|
|
3. **API follows entity**: API는 엔티티 관계에서 도출
|
|
4. **Traceability**: 모든 설계는 spec과 연결
|
|
|
|
---
|
|
|
|
## Next Steps
|
|
|
|
### 이 명령어 실행 후:
|
|
|
|
**📍 7단계 완료!**
|
|
- 기획부터 설계까지 모든 문서 완성
|
|
- 개발팀에게 전달 가능
|
|
- MVP Phase 0 개발 시작
|
|
|
|
---
|
|
|
|
## Version
|
|
|
|
- **Version**: 1.0.0
|
|
- **Created**: 2025-11-20
|
|
- **Philosophy**: "설계는 기획과 구현 사이의 다리"
|