# Agent 미팅: YouTube 전사/요약 파이프라인 — InsuWiki 지적자산화

**날짜**: 2026-03-26
**소집 이유**: 유튜브 보험 채널의 신규 영상을 자동 전사/요약하여 InsuWiki 검색 가능 지적자산으로 만드는 파이프라인 Best 구현 방안 결정
**참여 페르소나**: 토르(백엔드), 프레이야(프론트엔드), 미미르(UX/IA), 헤임달(QA), 로키(레드팀)
**미팅 모드**: hybrid
**토론 깊이**: thorough
**총 사이클 수**: 2

---

## Cycle 1 (Independent Round)

### 오딘 분석

기존 시스템 현황:
- `crawlYoutubeChannels.ts` (Cloud Functions, 918줄): 전체 파이프라인 이미 구현
- Cloud Functions에서 localhost:8200 Whisper 서비스를 Cloudflare Tunnel 경유 호출 → 구조적 결함
- Firestore 5개 컬렉션: youtube_knowledge, youtube_transcripts, youtube_summaries, insurance_chunks, youtube_summary_queue
- 프론트엔드: 전용 유튜브 페이지 없음, insurance_chunks RAG 통합만 존재
- conflictsWithPolicy 항상 false (Phase 2로 미뤄진 상태)

핵심 쟁점: 제이회장님은 "서버에서 단순하게" 원하시는데, 기존 Cloud Functions에 이미 상당 부분 구현됨. 어떤 방향이 Best?

### 페르소나 의견

**토르(Thor) — 백엔드**:
- Cloud Functions→localhost 호출은 Cloudflare Tunnel(임시 URL) 의존으로 SPOF
- 540초 타임아웃 < Whisper 600초 → 긴 영상 처리 불가
- 권장: 하이브리드(CF 오케스트레이션 + 서버 GPU) 또는 역전 구조(서버가 Firestore 큐 폴링)
- 처리 상태 추적(youtube_processing_state) 컬렉션으로 재시도 가능하게
- Pub/Sub 큐로 영상별 분리 처리 제안

**프레이야(Freyja) — 프론트엔드**:
- RAG 통합만으로는 "이번 달 영상에서 실손 관련 뭐라고 했지?" 같은 탐색 불가
- Phase 1: AnswerCard 유튜브 배지 개선 (클릭 링크, channelName, publishedAt, transcriptionSource 배지)
- Phase 2: /youtube 독립 탐색 페이지 (채널 chip 필터 + 날짜 + 키워드)
- 영상 임베드: 썸네일+링크 즉시 구현, 타임스탬프 딥링크는 나중
- 시나리오: 상담 전 조사, 고객 반론 준비, 팀 내 지식 공유

**미미르(Mimir) — UX/IA**:
- 단일 분류 체계 실패 → 3-Entry Point 구조 (최신 피드, 채널별 뷰, 주제별 태그)
- **핵심**: insurance_chunks에서 youtube 분리가 최우선 (권위 혼동, 검색 노이즈)
- "연결된 분리(Connected Separation)": 약관 검색과 유튜브 보조 검색 별도 경로
- 규모별 UX 진화: 100개=브라우징 → 500개=필터링 → 1000개=추천
- title_description 영상은 검색 인덱스 제외 원칙

**헤임달(Heimdall) — QA**:
- TOP 3 위험: ① 상태 없는 멱등성 ② Whisper fallback 텍스트 DB 오염 ③ LLM 수치 환각
- summaryStatus: 'processing' 중간 상태 추가 필요
- Circuit Breaker 패턴으로 Whisper 서비스 장애 대응
- fact_guard.py 연동으로 수치 환각 방어
- title_description fallback 영상은 요약 생성 자체 금지

**로키(Loki) — 레드팀**:
- **#1 CRITICAL**: 잘못된 전사→금소법 위반. conflictsWithPolicy 항상 false, 인간 검토 없이 RAG 즉시 노출
- #2: Cloud Function localhost 호출 — 설정 누락 시 조용한 Track B 비활성화
- #3: 단일 GPU 서버 SPOF
- #4: YouTube ToS 위반 (yt-dlp + InnerTube)
- #5: OAuth2 Refresh Token 6개월 만료 → Drive 업로드 전면 실패
- 보험 전문 용어 오인식 → 수치 오류 → 금소법 19조 위반 연쇄 위험

### Cycle 1 합의
- Cloud Functions 현재 구조는 구조적 결함 (전원 합의)
- 금소법 위험이 최우선 해결 과제 (전원 합의)
- insurance_chunks에서 youtube 분리 필요 (전원 합의)
- 처리 상태 추적 필요 (전원 합의)

### 미해결 항목
- 서버 Python 전면 이전 vs Cloud Functions 하이브리드
- 승인 큐 구현 방식 (Firestore 큐 vs Google Sheets vs 기타)

---

## Cycle 2 (DA Round)

### Devil's Advocate
**지정**: 로키(Loki)

1. **실패 시나리오**: 서버 크론이 조용히 실패 — Cloud Functions는 실패 시 Firebase 콘솔 알람이 뜨지만 서버 크론은 2주째 멈춰도 아무도 모름
2. **후회 이유**: 승인 큐 방치 — 월 90-150건 승인 요청 → 3주차부터 밀림 → RAG 인덱스 한 달 전 데이터로 정체. 시간적 일관성 붕괴가 금소법 관점에서 더 위험할 수 있음
3. **더 단순한 대안**:
   - YouTube 공식 자막만 사용 (Whisper는 fallback으로만) → 파이프라인 복잡도 절반
   - Google Sheets를 승인 큐로 사용 → 개발 공수 0, 제이회장님이 익숙한 인터페이스
   - InsuWiki RAG와 완전 분리 → RAG 오염 리스크 제로

**반박**:
1. 크론 조용한 실패 → **수용**. 모니터링을 필수 구현: 실행 후 Telegram 보고, 실패 시 즉시 알림
2. 승인 큐 방치 → **부분 수용**. Google Sheets 승인이 실용적. 또는 "수치 포함 요약만 검토 큐에, 나머지는 자동 게시" 하이브리드
3. YouTube 자막 우선 → **수용**. 이미 3-tier 구조(Caption→Whisper→Title)와 동일. Whisper는 자막 없는 영상 전용 fallback
4. RAG 완전 분리 → **기각**. 제이회장님이 "InsuWiki에서 검색 가능하게" 명시. 다만 즉시 RAG 반영이 아닌 별도 컬렉션 저장 후 승인 시 반영

**판정**: DA 우려 대부분 타당. 설계 수정 반영.

### 비관습적 대안
**제시자**: 로키

**대안**: Google Sheets 승인 큐 + 자동 수치 경고
- Google Sheets에 처리 결과 행 추가 → 제이회장님이 체크박스 → Apps Script가 Firestore 반영
- 수치(숫자+단위) 포함 요약은 노란색 경고 표시
- 개발 공수: 최소 (Google Sheets + Apps Script)
- 제이회장님이 이미 익숙한 인터페이스

**5개 항목 평가**:
1. 최강 지지 논거: 개발 공수 거의 0, 제이회장님 UX 최적
2. 최강 반론: Apps Script 유지보수 부담, Sheets API 할당량
3. 이상적 사용 시나리오: 채널 10개 이하, 일 처리량 10건 미만
4. 노력 수준: 낮음
5. 리스크 등급: 낮음

**판정**: **채택**. 초기 구현으로 적합. 규모가 커지면 대시보드 내 승인 UI로 전환.

---

## 최종 합의 사항

### 1. 아키텍처: 서버 Python 파이프라인 (Cloud Functions 폐기)
- 아누 서버(100.76.130.39)에서 Python 스크립트로 전체 파이프라인 실행
- 크론(crontab 또는 cokacdir --cron)으로 스케줄링
- Whisper GPU와 같은 서버 → 네트워크 홉 제거, 타임아웃 제한 없음
- Firestore: Python firebase-admin SDK (서비스 계정 키)
- Google Drive: Python google-api-python-client
- **필수**: 실행 후 Telegram 보고 + 실패 시 즉시 알림 (크론 조용한 실패 방지)

### 2. 파이프라인 흐름
```
[크론 6시간마다]
  ↓
[YouTube Data API — 채널별 신규 영상 체크]
  ↓ (lastCrawledAt 이후 영상)
[전사 3-tier]
  ├─ Track A: YouTube 공식 자막 (우선)
  ├─ Track B: Whisper GPU fallback (자막 없을 때만)
  └─ Track C: 제목+설명 fallback (A,B 모두 실패 시 — 요약 생성 금지)
  ↓
[LLM 요약 — Gemini 2.5 Flash]
  ↓ (Track C는 스킵)
[Google Drive 업로드 — 전사파일 + 요약파일]
  ↓
[Firestore youtube_knowledge 메타데이터 저장]
  ↓
[Google Sheets 승인 큐에 행 추가]
  ↓ (제이회장님 승인 후)
[insurance_chunks RAG 인덱스 반영]
```

### 3. 금소법 대응: 2단계 품질 게이트
- **1단계 자동**: Track C(제목+설명만)는 요약 생성 금지. 수치(숫자+단위) 포함 요약에 경고 플래그.
- **2단계 수동**: Google Sheets 승인 큐에 처리 결과 기록 → 제이회장님 검토 → 체크박스 → Firestore insurance_chunks 반영

### 4. Firestore 스키마
- youtube_knowledge: 기존 스키마 호환 유지 (videoId, channelId, title, publishedAt, chunkText, embedding 등)
- 추가 필드: `approvalStatus: 'pending' | 'approved' | 'rejected'`, `approvedAt`, `sheetsRowId`
- insurance_chunks: approvalStatus='approved'인 것만 반영 (RAG 오염 방지)

### 5. InsuWiki 프론트엔드 (Phase 분리)
- **Phase 1** (즉시): insurance_chunks에서 youtube sourceType 분리 + AnswerCard 배지 개선
- **Phase 2** (100개 도달 시): /youtube 독립 탐색 페이지
- **Phase 3** (500개 도달 시): 주제 태그, 채널 프로필, 열람 히스토리

### 6. 모니터링
- 파이프라인 실행 후 Telegram 보고 (신규 영상 수, 성공/실패, 처리 방식)
- Whisper 서비스 health check (크론 실행 전 /v1/health 확인)
- Drive OAuth2 토큰 만료 사전 알림

### 7. 기존 Cloud Functions 파이프라인 관계
- crawlYoutubeChannels.ts: 신규 Python 파이프라인 안정화 후 폐기 (즉시 폐기 아님)
- 전환 기간: 양쪽 병행 운영, Python 파이프라인이 2주 이상 안정적으로 동작 확인 후 CF 비활성화

---

## 미해결 항목

- [OPEN] Google Sheets 승인 큐의 구체적 시트 구조 설계
- [OPEN] Apps Script → Firestore 반영 스크립트 구현
- [OPEN] conflictsWithPolicy 자동 감지 로직 (Phase 2)
- [OPEN] YouTube ToS 리스크 대응 (yt-dlp 대안 검토)
- [OPEN] 서비스 계정 키 파일 보안 관리 방안

---

## Temporal Interrogation (시간대별 결정사항)

### [HOUR 1] 작업 시작
- [RESOLVED] Python 환경: 기존 서버 Python 3.11+ 사용
- [RESOLVED] 스크립트 위치: `/home/jay/workspace/scripts/autoresearch/` 하위
- [OPEN] Firebase 서비스 계정 키 파일 경로 — `/home/jay/workspace/secrets/`에 보관, .gitignore 필수
- [RESOLVED] 의존성: firebase-admin, google-api-python-client, google-auth, requests

### [HOUR 2-3] 핵심 구현
- [RESOLVED] YouTube 신규 영상 감지: YouTube Data API playlistItems.list + lastCrawledAt 비교
- [RESOLVED] 전사 3-tier: Caption(yt-dlp --list-subs) → Whisper(localhost:8200) → title+desc
- [RESOLVED] 요약: Gemini 2.5 Flash, 기존 YOUTUBE_SUMMARY_PROMPT 재사용
- [OPEN] Gemini API 키 관리 — 환경변수 vs .env 파일
- [RESOLVED] Drive 폴더 구조: 기존과 동일 (04_유튜브요약/{channelName}/)

### [HOUR 4-5] 통합
- [OPEN] Google Sheets 연동 구현 — gspread 라이브러리 사용
- [RESOLVED] Firestore youtube_knowledge 스키마: 기존 호환 + approvalStatus 추가
- [RESOLVED] 처리 상태 추적: summaryStatus에 'processing' 추가

### [HOUR 6+] 마무리
- [RESOLVED] 모니터링: Telegram 보고 (cokacdir --sendfile로 처리 로그 전송)
- [OPEN] 크론 등록 방식 — crontab vs cokacdir --cron
- [RESOLVED] 테스트: 실제 보험 영상(짧은 것)으로 E2E 테스트, 결과물 제이회장님 확인 전 삭제 금지

---

## 다음 단계

이 미팅 결과를 기반으로 구현 작업을 위임합니다.
- 서버 Python 파이프라인 구현 → 개발팀에 위임
- Google Sheets 승인 큐 설계 → 함께 구현
- InsuWiki 프론트엔드 Phase 1 → 별도 위임
