6. AI — ExerciseLibrary·ProgramTemplate·Phase·AIRecommendation·LLMCallLog
시스템 PT의 핵심 데이터. 4C AI 역할 정책 반영.
ExerciseLibrary
Purpose: 본사 표준 운동 라이브러리. 멘토·AI 모두 참조하는 운동 종목 카탈로그. Related PRDs: 🏢 AI 엔진 · 👤 AI 가이드 Lifecycle: 운영자 추가 → 활성 → (deprecate 가능)
Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| id | String | ✓ | cuid() | PK |
| name | String | ✓ | - | “데드리프트” |
| nameEn | String? | - | null | “Deadlift” |
| category | String | ✓ | - | upper/lower/cardio/core/fullbody |
| muscleGroups | String[] | - | [] | [“햄스트링”, “둔근”] |
| defaultSets | Int? | - | 3 | |
| defaultRepsMin | Int? | - | 8 | |
| defaultRepsMax | Int? | - | 12 | |
| intensityCurve | Json? | - | null | 진행률별 강도 룰 |
| formVideoUrl | String? | - | null | 5초 영상 |
| safetyNotes | Text? | - | null | 주의 사항 |
| status | String | ✓ | active | active/deprecated |
| createdAt | DateTime | ✓ | now() |
Indexes
[category, status]— 카테고리별 가용 운동
Common Queries
- 카테고리별 운동:
WHERE category=? AND status='active' - 근육군별:
WHERE 'hamstring' = ANY(muscleGroups)
ProgramTemplate
Purpose: Phase별 운동 프로그램 (근비대 Phase 2/4 4주차 등). Related PRDs: 🏢 AI 엔진 Lifecycle: 본사 운영팀 제작 → 활성 → 회원 적용
Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| id | String | ✓ | cuid() | PK |
| phaseType | String | ✓ | - | hypertrophy/strength/fatloss/recovery |
| phaseLabel | String | ✓ | - | “근비대” |
| stage | Int | ✓ | - | 1-4 |
| weekInStage | Int | ✓ | - | 1-N |
| exercises | Json | ✓ | - | ExerciseLibrary 참조 + 강도 룰 |
| difficulty | String | ✓ | - | beginner/intermediate/advanced |
| status | String | ✓ | active |
exercises Json 스키마
[
{
"exerciseId": "ex_deadlift",
"section": "main", // warmup/main/accessory
"sets": 4,
"intensityRule": "previous_weight + 5%",
"alternatives": ["ex_rdl", "ex_good_morning"]
}
]
Indexes
[phaseType, stage, weekInStage, difficulty]— 매칭
Common Queries
- Phase 매칭:
WHERE phaseType=? AND stage=? AND weekInStage=? AND difficulty=?
Phase
Purpose: 회원의 현재 운동 Phase 추적. Related PRDs: 👤 AI 가이드 Lifecycle: 신규 회원 입문 시작 → Phase 진행 → 다음 단계 자동 전환
Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| id | String | ✓ | cuid() | PK |
| memberId | String | ✓ | - | FK (unique) |
| phaseType | String | ✓ | - | hypertrophy/… |
| phaseLabel | String | ✓ | - | “근비대” |
| stage | Int | ✓ | 1 | 1-4 |
| weekInStage | Int | ✓ | 1 | |
| weeksTotal | Int | ✓ | 24 | 전체 주차 (4 stage × 6주 등) |
| startedAt | DateTime | ✓ | now() | |
| nextStageAt | DateTime? | - | null | 자동 계산 |
| progressPercent | Decimal? | - | null | 0-100 |
| customNotes | Text? | - | null | AI/멘토 코멘트 |
Validation
- memberId unique (1 phase per member at any time)
- stage 1-4, weekInStage 1-12 (가설)
Indexes
memberId(unique)
Common Queries
- 회원 현재 phase:
WHERE memberId=? - Phase 전환 임박:
WHERE nextStageAt < NOW() + 7d
Edge Cases
- 부상·일시정지 → phase 일시 보류 (별도 status 컬럼 검토)
- 회원 운동 정체 → AI가 weekInStage 정체 시 보강 운동 추천
AIRecommendation
Purpose: 회원의 다음 세션 운동 추천 (AI 생성). 시스템 PT 핵심. Related PRDs: 🏢 AI 엔진 · 👤 AI 가이드 Lifecycle: 세션 예약 직후 생성 → 세션 직전 갱신 (멘토 인계 반영) → 세션 후 새로 생성
Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| id | String | ✓ | cuid() | PK |
| memberId | String | ✓ | - | FK |
| forSessionId | String? | - | null | 특정 세션용 (1:1) |
| forSessionAt | DateTime | ✓ | - | 추천 적용 시각 |
| generatedAt | DateTime | ✓ | now() | |
| plan | Json | ✓ | - | cardio + room_autonomous_30 + mentor_30 |
| rationale | Text? | - | null | “지난 60kg → 65kg 시도” |
| sourceSessionIds | String[] | ✓ | [] | 학습에 쓴 세션 IDs |
| modelVersion | String? | - | null | “claude-sonnet-4-6” 등 |
| llmCostKrw | Decimal(8,2)? | - | null | 호출 비용 |
| status | String | ✓ | active | active/superseded |
plan Json 스키마
{
"cardio": {
"type": "런닝",
"durationMin": 25,
"intensity": "심박 130-150",
"intervals": [...]
},
"roomAutonomous30Min": [
{ "exerciseId": "ex_deadlift", "sets": 4, "weight": 65, "reps": 5, "category": "main" }
],
"mentor30Min": [
{ "exerciseId": "ex_squat", "sets": 4, "weight": 55, "reps": 8 }
]
}
Validation
- (memberId, forSessionId) 1:1 (한 세션 = 1 active 추천)
- 갱신 시 이전 추천 status=’superseded’
Indexes
forSessionId(unique active)[memberId, generatedAt]— 최신 추천 조회
Common Queries
- 다음 세션 추천:
WHERE forSessionId=? AND status='active' - 회원 최근 추천 히스토리:
WHERE memberId=? ORDER BY generatedAt DESC LIMIT 10
Edge Cases
- LLM timeout → 룰 기반 fallback (직전 N세션 + Phase template)
- 멘토 인계 메모가 강도 ↓ 요청 → AI 가중치 적용
- 회원이 추천 안 따라감 → 다음 추천 시 보정
LLMCallLog
Purpose: LLM 호출 비용·성능 추적. 회원당 월 비용 한도 관리. Related PRDs: 🏢 AI 엔진 · 🚀 인프라 Lifecycle: 호출마다 로그 → 일별·월별 집계
Fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| id | String | ✓ | cuid() | PK |
| model | String | ✓ | - | “claude-sonnet-4-6” |
| provider | String | ✓ | - | “anthropic” / “openai” |
| tokensIn | Int | ✓ | - | input tokens |
| tokensOut | Int | ✓ | - | output tokens |
| costKrw | Decimal(8,2) | ✓ | - | 원화 환산 |
| memberId | String? | - | null | (있을 시) |
| sessionId | String? | - | null | |
| purpose | String | ✓ | - | “recommendation”/”monthly_analysis”/”summary” |
| latencyMs | Int? | - | null | |
| success | Boolean | ✓ | true | |
| errorMessage | String? | - | null | |
| createdAt | DateTime | ✓ | now() |
Indexes
[memberId, createdAt]— 회원별 월 비용[provider, createdAt]— 비용 모니터링[purpose]— 용도별 분석
Common Queries
- 회원 이번 달 AI 비용:
SUM(costKrw) WHERE memberId=? AND createdAt >= MONTH_START - 일별 총 비용:
SUM GROUP BY DATE(createdAt) - 실패 호출 비율:
COUNT WHERE success=false / COUNT total
Edge Cases
- 회원당 월 비용 한도 초과 (10,000원) → fallback (룰 기반) + 알림
- 일별 총 비용 폭증 → Slack 알림 (#alerts-critical)
📘 사용 PRD
| 2026-05-13 | 초안 — AI 5 모델 상세 명세 |