Files
appkit/.claude/commands/appkit.design.md
rupy1014 f4b14fddf5 Initial commit
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-21 07:07:35 +09:00

16 KiB

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

/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

# 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_idPersona.id (N:1)
  • Content.idPost.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_idContent.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):

{
  "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):

{
  "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:

{
  "persona_id": 1,
  "topic": "오늘의 운동 루틴",
  "auto_post": false
}

Success Response (201 Created):

{
  "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):

{
  "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:

{
  "execution_time": "07:00",
  "target_personas": [1, 2, 3],
  "is_active": true
}

Success Response (201 Created):

{
  "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:

{
  "content_id": 101,
  "platform": "instagram",
  "scheduled_at": "2025-01-01T12:00:00Z"
}

Success Response (201 Created):

{
  "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:

{
  "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

# 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**: "설계는 기획과 구현 사이의 다리"