---
task_id: task-2136
type: context
scope: task
created: 2026-04-23
updated: 2026-04-23
status: in-progress
---

# 맥락 노트: task-2136

**task**: task-2136

---

## 결정 근거

### 3 Step Why 자문

**1st Why: "왜 BaseCollector 추상 클래스 + NaverCollector 패턴이 필요한가?"**
→ A: 현재 trend_collector.py는 pytrends 전용 단일 수집기. 네이버 검색광고 API, 향후 유료 API(SerpAPI 등) 추가 시 코드 중복 불가피. Collector 인터페이스 추상화로 확장성 확보.

**2nd Why: "왜 A(추상 클래스 패턴)가 최선의 접근인가?"**
→ B: 에이전트 미팅에서 오딘이 "pytrends 라이브러리 death" 리스크를 지적. Collector 인터페이스를 분리하면 수집 소스 교체 시 상위 코드 변경 없이 새 Collector만 추가. Template Method 패턴으로 collect→normalize→filter→run 파이프라인 보장.

**3rd Why: "왜 B(Template Method)가 다른 대안보다 나은가?"**
→ C: 대안 1) Strategy 패턴: 유연하나 과설계. MVP에서는 수집기가 2종뿐이므로 Template Method로 충분. 대안 2) 함수형 파이프라인: 테스트 용이하나 상태(DB 연결, API 인증) 관리가 클래스 기반보다 복잡. ABC + Template Method가 Python에서 가장 관용적이고 확장 시 최소 변경.

**논리 일관성**: A→B→C 모두 "확장성 + 관용성 + MVP 적절성"으로 연결됨. ✅

### 네이버 검색광고 API 인증
- HMAC-SHA256 서명: timestamp.method.path → base64 인코딩
- 기존 main.py의 naver_proxy 엔드포인트에 동일 패턴 구현 완료 (line 815-865)
- 환경변수: NAVER_SEARCHAD_CUSTOMER_ID, NAVER_SEARCHAD_API_KEY, NAVER_SEARCHAD_SECRET_KEY

### 기존 코드 래핑 전략
- trend_collector.py의 collect_trends() 함수를 FixedCollector에서 90% 재활용
- get_supabase() 함수 → BaseCollector.__init__에서 Supabase 클라이언트 공유

## 참조 자료

- 미팅 기록: `/home/jay/workspace/memory/meetings/2026-04-23-google-trends-architecture.md`
- 기존 수집기: `/home/jay/projects/InsuRo/server/trend_collector.py`
- 기존 API: `/home/jay/projects/InsuRo/server/main.py`
- 기존 프론트: `/home/jay/projects/InsuRo/src/pages/KeywordAnalysis.tsx`

### Codex 게이트 리스크 대응 (2026-04-23)

| 리스크 | 심각도 | 대응 |
|--------|--------|------|
| is_active↔status 호환 | critical | status 컬럼 추가하되 is_active 유지. status='active' ↔ is_active=True 동기화. 기존 코드 수정 없이 호환 |
| last_collected_at 누락 | high | last_collected_at TIMESTAMPTZ 컬럼 추가. 수집 시 갱신. 신뢰도/inactive 산출에 사용 |
| NaverCollector 프록시 재사용 | high | 기존 프록시(main.py:815-876) 참조만. NaverCollector에 독립 파이프라인: 정규화→5개 배치→병합→보험필터→상위70 |
| 고정키워드 원본 이중화 | medium | DB 시드(002_trend_seed_keywords.sql)가 원본. config/fixed_keywords.txt는 DB sync로 생성/참조용 |
| 프론트 탭 레이아웃 | medium | grid-cols-5 → responsive 대응. 기존 탭 옆에 "키워드 순위" 탭 추가 |
| 유사 키워드 추천 | medium | DB의 trigram similarity(pg_trgm) 활용, 상위 3건 반환 |

## 주의사항

- pytrends 429 rate limit: 키워드 간 30~60초 딜레이 유지
- 네이버 API 호출: batch 당 hintKeywords 5개 제한
- DB 컬럼 추가는 ALTER TABLE IF NOT EXISTS 사용 (멱등성)
- 네거티브 키워드 필터링: 법적 리스크 키워드 반드시 제거 (보험사기, 소송 등)
- is_active 필드를 제거하지 않음 — status 컬럼과 이중 유지하여 기존 코드 호환
- last_collected_at 필드 추가로 신뢰도/inactive 정확 산출
