OTT가 넘쳐나는 시대. 넷플릭스, 티빙, 웨이브, 디즈니+, 쿠팡플레이, 왓챠… 매번 앱을 넘나들며 "뭘 볼까" 고민하는 시간이 실제 시청 시간보다 길었습니다.
"사용자의 감정과 맥락을 이해하는 AI가 한국 OTT 6개를 한 번에 검색하고, 왜 이 콘텐츠를 추천하는지 근거까지 보여주면 검색 피로도를 해결할 수 있다."
| 결정 | 선택 | 기획적 근거 |
|---|---|---|
| 검색 방식 | 하이브리드 (벡터+키워드) |
키워드 검색만으로는 "우울한데 뭐 볼까"를 처리 못함. 벡터 유사도(pgvector) + PostgreSQL FTS를 결합하여 감정 기반 검색 구현 |
| 추천 응답 | SSE 5-청크 스트리밍 |
사용자가 3초 이상 기다리면 이탈. 생각 과정→콘텐츠→설명 순서로 점진 노출하여 체감 대기시간 최소화 |
| 의도 분석 | 자체 IntentParser | "넷플릭스에서 액션 말고 로맨스" · OTT 필터, 장르 포함/제외, 부정어(말고/빼고/싫어 등 6종)를 정규식으로 파싱 |
| 에이전트 구조 | 다중 자율 에이전트 파이프라인 | 크롤링·분석·추천·최적화를 독립 실행 → 장애 격리 + 병렬 처리. 하나가 죽어도 전체 서비스 유지 |
| 가용성 검증 | OTT별 크로스체크 | "이 콘텐츠 추천했는데 내 OTT에 없네" 문제 방지 · 딥링크 전 가용성 100% 확인 |
graph LR
subgraph BE["백엔드 · FastAPI"]
API["API 라우터 7개"] --> IP["IntentParser
감정·OTT·장르·부정어"]
IP --> RE["RecommendEngine
423줄 핵심 엔진"]
RE --> HS["HybridSearch
벡터+키워드"]
RE --> GC["Gemini Client
추천 생성"]
RE --> RC["Cache
결과 캐싱"]
HS --> DB[("Supabase
pgvector")]
end
FE["프론트엔드
Next.js 62p"] -->|"쿼리"| API
RE -.->|"SSE 5-청크"| FE
| 서비스 | 규모 | 역할 |
|---|---|---|
| RecommendEngine | 423줄 15KB | SSE 5-청크 스트리밍 핵심 엔진 · thought→metadata→message→xai→actions |
| HybridSearch | 7.4KB | 키워드(PostgreSQL FTS) + 벡터(pgvector) 하이브리드 검색 |
| EmbeddingService | 6.4KB | Gemini Embedding API · 콘텐츠 벡터 임베딩 생성 |
| GeminiClient | 6.9KB | Gemini API 클라이언트 · 스트리밍 응답 지원 |
| TMDBClient | 6.2KB | TMDB 영화/TV 데이터 수집 · 메타데이터 소스 |
| RecommendCache | 5.4KB | 추천 결과 Redis/InMemory 캐싱 |
| OTTAvailability | · | OTT 플랫폼별 콘텐츠 가용성 크로스체크 |
| DB | 7.8KB | Supabase 연결 관리 |
| 에이전트 | 규모 | 주기 | 역할 |
|---|---|---|---|
| SubscriptionOptimizer | 19.6KB | 주간 | 시청 패턴 기반 최적 OTT 조합 시뮬레이션 |
| ContentCrawler | 17.2KB | 일간 | 한국 OTT 6개 신규 콘텐츠 자동 크롤링 |
| ReviewAnalyzer | 17.5KB | 일간 | 리뷰 감성 분석 + 핵심 키워드 추출 |
| PipelineResilience | 16.9KB | 상시 | 장애 감지 → 자동 재시도 → 텔레그램 알림 |
| YoutubeCurator | 15.8KB | 일간 | 추천 콘텐츠와 예고편 자동 매칭 |
| Recommendation | 13.2KB | 실시간 | 추천 로직 오케스트레이션 |
| YouTubeQuotaManager | 7KB | 상시 | YouTube API 일일 10,000유닛 쿼터 최적 분배 |
| TrendRanker | 5.3KB | 일간 | SNS 버즈 + 검색량 + TMDB 인기도 기반 순위 |
| Orchestration | 2.8KB | 트리거 | 에이전트 실행 순서 조율 · 의존성 기반 DAG 실행 |
| 영역 | 규모 | 핵심 |
|---|---|---|
| src/app/ | 62 페이지 | 검색·추천·마이페이지·콘텐츠 상세·구독 관리 |
| src/components/ | 30 컴포넌트 | ContentCard, RecommendChat, OTTBadge, PriceCompare 등 |
| src/lib/ | 15 유틸 | Supabase 클라이언트, TMDB 헬퍼, 공통 유틸리티 |
| e2e/ | 4건 | Playwright E2E 테스트 (추천 흐름, 검색, 구독) |
사용자가 "우울한데 넷플릭스에서 뭐 볼까"를 입력했을 때의 전체 흐름.
sequenceDiagram
actor User as 사용자
participant FE as 프론트엔드
participant IP as IntentParser
participant RE as RecommendEngine
participant GM as Gemini API
participant DB as Supabase
User->>FE: "우울한데 넷플릭스에서 뭐 볼까"
FE->>IP: 쿼리 전송
IP->>IP: 감정→장르 매핑 (우울→드라마,로맨스)
Note over IP: OTT 필터: 넷플릭스
IP->>RE: QueryIntent 전달
RE->>DB: 하이브리드 검색 (벡터+FTS)
DB-->>RE: 후보 콘텐츠 20건
RE-->>FE: SSE 1: thought (추론 과정)
RE->>GM: 후보 기반 추천 요청
GM-->>RE: 추천 텍스트 생성
RE->>DB: OTT 가용성 크로스체크
RE-->>FE: SSE 2: metadata (콘텐츠 카드)
RE-->>FE: SSE 3: message (추천 설명)
RE-->>FE: SSE 4: xai (AI 확신도 + 근거)
RE-->>FE: SSE 5: actions (넷플릭스 딥링크)
FE-->>User: 결과 점진 표시