# 콘텐츠 기획 & 전략 수립 기능 구현 계획 ## Context 현재 INFINITH 파이프라인은 3-phase (discover → collect → generate-report)까지 완성되어 있고, DB 스키마에는 `content_plans`, `performance_metrics`, `strategy_adjustments`, `content_performance` 테이블이 이미 설계되어 있다. 하지만: - **콘텐츠 플랜 생성 Edge Function이 없다** — `content_plans` 테이블은 비어 있음 - **`contentDirector.ts`는 완전 deterministic** — AI 호출 없이 하드코딩 템플릿으로 캘린더 생성 - **PerformancePage는 mock 데이터** — 실제 DB 연동 없음 - **전략 조정 루프가 없다** — 성과 → 전략 피드백 메커니즘 미구현 이 기능은 파이프라인 Phase 4로 자연스럽게 확장되며, 기존 데이터 흐름 위에 AI 전략 계층을 추가한다. --- ## Phase 1: `generate-content-plan` Edge Function + 타입 확장 ### 1-1. Edge Function 생성 **새 파일:** `supabase/functions/generate-content-plan/index.ts` - [x] `generate-report/index.ts` 패턴 그대로 따름 (CORS, service role, Deno.serve) - [x] Input 인터페이스: `{ reportId, clinicId?, runId? }` - [x] `analysis_runs` (또는 `marketing_reports`)에서 channelAnalysis, kpiTargets, recommendations, services 읽기 - [x] Perplexity sonar 호출 (temp=0.3, 짧은 프롬프트) - System: `"You are a Korean medical marketing content strategist. Respond ONLY with valid JSON."` - User: 채널 점수 요약 + 서비스 목록 + KPI 타겟 + 전략 생성 요청 - [x] JSON 파싱 (기존 regex 패턴 재사용) - [x] `content_plans` 테이블에 INSERT (`is_active=true`, 이전 플랜 비활성화) - [x] AI 실패 시 fallback: deterministic `contentDirector.ts` 결과 사용 **AI 출력 스키마:** ```json { "channelStrategies": [{ "channelId", "targetGoal", "contentTypes", "postingFrequency", "priority" }], "contentPillars": [{ "title", "description", "relatedUSP", "exampleTopics" }], "calendar": { "weeks": [{ "weekNumber", "label", "entries": [...] }], "monthlySummary": [...] }, "postingSchedule": { "bestTimes", "rationale" } } ``` ### 1-2. CalendarEntry 타입 확장 **수정:** `src/types/plan.ts` (line 107-113) - [x] `id?: string` — UUID (드래그&드롭, 개별 재생성용) - [x] `description?: string` — AI 생성 가이드 - [x] `pillar?: string` — 콘텐츠 필러 연결 - [x] `status?: 'draft' | 'approved' | 'published'` - [x] `isManualEdit?: boolean` — AI 덮어쓰기 방지 플래그 - [x] `aiPromptSeed?: string` — 개별 재생성 컨텍스트 ### 1-3. 데이터 레이어 **수정:** `src/lib/supabase.ts` - [x] `generateContentPlan(reportId, clinicId?, runId?)` — Edge Function 호출 - [x] `fetchActiveContentPlan(clinicId)` — content_plans 쿼리 - [x] `updateCalendarEntry(planId, entryId, updates)` — JSONB 패치 **수정:** `src/hooks/useMarketingPlan.ts` - [x] 데이터 소스 우선순위: content_plans → navigation state → marketing_reports --- ## Phase 2: Enhanced Content Calendar UI ### 2-1. ContentCalendar 인터랙티브 업그레이드 **수정:** `src/components/plan/ContentCalendar.tsx` - [x] `useState`로 로컬 편집 상태 관리 - [x] 엔트리 클릭 → EditEntryModal 열기 - [x] Status 뱃지 (gray=draft, purple=approved, green=published) - [x] 엔트리 hover 시 AI 재생성 버튼 - [x] Weekly/Monthly 뷰 토글 - [x] 채널/콘텐츠 타입 필터 ### 2-2. EditEntryModal 생성 **새 파일:** `src/components/plan/EditEntryModal.tsx` - [x] Title, Description, Channel, Content Type, Day, Status 필드 - [x] "AI 재생성" 버튼 (aiPromptSeed 기반) - [x] Save / Cancel 버튼 - [x] 기존 디자인 시스템 적용 (rounded-2xl, shadow, purple accent) --- ## Phase 3: Strategy Adjustment Loop ### 3-1. adjust-strategy Edge Function **새 파일:** `supabase/functions/adjust-strategy/index.ts` - [x] Input: `{ clinicId }` - [x] `channel_weekly_delta` 뷰로 최근 채널 변화량 조회 - [x] 활성 `content_plans` 조회 - [x] `analysis_runs.report`에서 kpiTargets 추출 - [x] KPI 달성률 계산 - [x] Perplexity sonar로 조정 추천 생성 - [x] `performance_metrics` INSERT (channel_deltas, kpi_progress, strategy_suggestions) - [x] `strategy_adjustments` INSERT (adjustment_type, before/after values) ### 3-2. StrategyAdjustmentSection **새 파일:** `src/components/plan/StrategyAdjustmentSection.tsx` - [x] KPI 진행률 프로그레스 바 - [x] 전략 제안 카드 (수락/거절) - [x] 조정 이력 타임라인 --- ## Phase 4: 파이프라인 & 페이지 통합 ### 4-1. AnalysisLoadingPage에 Phase 4 추가 **수정:** `src/pages/AnalysisLoadingPage.tsx` - [x] `PHASE_STEPS`에 planning 단계 추가 - [x] `runPipeline`에서 generate-report 후 `generateContentPlan()` 호출 ### 4-2. MarketingPlanPage에 조정 섹션 추가 **수정:** `src/pages/MarketingPlanPage.tsx` - [x] AssetCollection 다음에 `` 추가 ### 4-3. PerformancePage 실제 데이터 연동 **수정:** `src/pages/PerformancePage.tsx` - [x] Mock 데이터 → 실제 DB 쿼리로 교체 - [x] "전략 조정 실행" 버튼 → `triggerStrategyAdjustment()` 호출 **새 파일:** `src/hooks/usePerformanceData.ts` - [x] `channel_snapshots`, `performance_metrics`, `content_performance` 통합 조회 ### 4-4. Route 업데이트 **수정:** `src/main.tsx` - [x] `/performance/:clinicId?` 형태로 변경 --- ## 파일 변경 요약 ### 새로 생성 (6) | 파일 | 목적 | Phase | |------|------|-------| | `supabase/functions/generate-content-plan/index.ts` | AI 콘텐츠 전략 생성 | 1 | | `supabase/functions/adjust-strategy/index.ts` | 성과 기반 전략 조정 | 3 | | `src/components/plan/EditEntryModal.tsx` | 캘린더 엔트리 편집 | 2 | | `src/components/plan/StrategyAdjustmentSection.tsx` | 전략 조정 UI | 3 | | `src/hooks/useContentPlan.ts` | content_plans 데이터 훅 | 1 | | `src/hooks/usePerformanceData.ts` | 성과 데이터 통합 훅 | 4 | ### 수정 (7) | 파일 | 변경 내용 | Phase | |------|-----------|-------| | `src/types/plan.ts` | CalendarEntry에 optional 필드 6개 추가 | 1 | | `src/hooks/useMarketingPlan.ts` | content_plans 우선 소스 추가 | 1 | | `src/lib/supabase.ts` | 새 API 함수 4개 추가 | 1 | | `src/components/plan/ContentCalendar.tsx` | 인터랙티브 UI 업그레이드 | 2 | | `src/pages/AnalysisLoadingPage.tsx` | Phase 4 파이프라인 추가 | 4 | | `src/pages/MarketingPlanPage.tsx` | StrategyAdjustment 섹션 추가 | 4 | | `src/pages/PerformancePage.tsx` | Mock → 실제 DB 데이터 | 4 | ### 변경 없음 (Fallback 유지) - `src/lib/contentDirector.ts` — deterministic fallback 엔진 - `src/lib/transformPlan.ts` — fallback 변환 - `supabase/functions/_shared/config.ts` — 재사용 --- ## 검증 체크리스트 - [x] Edge Function 테스트: `curl`로 `generate-content-plan` 호출 → `content_plans` 테이블 적재 확인 - [x] 프론트엔드 테스트: `npm run dev` → `/plan/:id` → content_plans 데이터 렌더링 확인 - [x] 캘린더 인터랙션: 엔트리 클릭 → 편집 → 저장 → 새로고침 후 유지 확인 - [x] 파이프라인 E2E: URL 입력 → 4단계 파이프라인 완료 → 플랜 페이지 자동 표시 - [x] 타입 체크: `npm run lint` (tsc --noEmit) 통과 ## 핵심 패턴 참조 파일 - `supabase/functions/generate-report/index.ts` — Edge Function 패턴 - `src/lib/contentDirector.ts` — 현재 deterministic 엔진 (fallback) - `src/hooks/useMarketingPlan.ts` — 데이터 소스 우선순위 체인 - `src/components/plan/ContentCalendar.tsx` — 현재 캘린더 UI