# task-2329 완료 보고서

**작업**: InsuRo 트렌드 인사이트 Phase 2 — 키워드 풀 한계 극복
**팀**: dev3-team (다그다 팀장, 루 백엔드, 브리짓 프론트엔드)
**레벨**: Lv.4 (한정승인)
**일시**: 2026-04-30

---

## S - Situation (현재 상황)
InsuRo 트렌드 인사이트 Phase 1이 완료된 상태. 17사이클 에이전트 미팅에서 Phase 2 구현 범위가 확정됨.

## C - Complication (문제)
기존 고정 풀(3,500개)만으로는 풀 밖에서 급등하는 키워드를 감지할 수 없는 근본적 한계가 있었음. 뉴스에 의한 급등, 시즌성 변동을 자동 포착해야 보험 FA의 블로그 경쟁력 확보 가능.

## Q - Question (핵심 질문)
DB 4테이블 + 급등 감지 + 뉴스 키워드 파이프라인 + 시즌 캘린더 부스트 + UI를 안전하게 구현할 수 있는가?

## A - Answer (답변)
Phase 2 백엔드 스크립트 5개, 마이그레이션 1개, 도메인 사전 1개, API 엔드포인트 1개, 프론트엔드 UI 1개를 구현하고 빌드 성공.

---

## 수정/생성 파일 목록

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| server/migrations/008_phase2_tables.sql | keyword_pool, news_keyword_candidates, surge_events, keyword_stats_monthly 4테이블 DDL | grep "CREATE TABLE" → 4건 | verified |
| server/scripts/daily_surge_detect.py | 직전 4주 같은 요일 기준 급등 감지 (200%/시즌300%) | grep "surge_pct" → 다수 | verified |
| server/config/insurance_domain_terms.json | 534개 보험 도메인 용어 사전 (8개 카테고리) | wc -l → 15588 bytes | verified |
| server/scripts/news_keyword_extract.py | 네이버 뉴스 API + 도메인 사전 매칭 + SearchAd 검증 + opt-out 자동 승인 | grep "auto_approved" → OK | verified |
| server/scripts/season_calendar_check.py | season_calendar.json 기반 시즌 부스트 + keyword_pool season_tags 업데이트 | grep "season_tags" → OK | verified |
| server/scripts/run_trend_pipeline.sh | Step 0 (시즌 체크) + Step 3.5 (급등 감지) 추가 | grep "Step 0" → OK | verified |
| server/scripts/keyword_data_compress.py | 90일 이전 keyword_trends → keyword_stats_monthly 롤업 + NOT EXISTS 가드 삭제 | grep "NOT EXISTS" → OK | verified |
| server/main.py:4314 | GET /api/insuro/trend-insight/surge-events 엔드포인트 | grep "surge-events" → OK | verified |
| src/components/keyword/TrendInsightTab.tsx | "오늘 뜨는 키워드" 섹션 + 배너 "3,500개" 업데이트 | grep "오늘 뜨는" → OK | verified |

---

## 테스트 결과

### py_compile (4개 스크립트)
- daily_surge_detect.py: PASS
- news_keyword_extract.py: PASS
- season_calendar_check.py: PASS
- keyword_data_compress.py: PASS

### 드라이런 테스트
- daily_surge_detect.py --dry-run: PASS (Supabase 연결 OK, 키워드 1000개 로드, 급등 0건 — 정상)
- season_calendar_check.py --dry-run: PASS (4/30 비시즌 → 기본 임계값 200% — 정상)
- keyword_data_compress.py --dry-run: PASS (90일 이전 데이터 없음 → 대상 없음 — 정상)
- news_keyword_extract.py: 외부 API 호출 포함으로 드라이런 타임아웃 (컴파일 PASS)

### npm run build
- 결과: 성공 (12.73s)
- TypeScript 오류: 0건
- dist/ 산출물 정상 생성

---

## L1 스모크테스트 결과

- 서버 재시작: 성공 (포트 8321, uvicorn)
- API 응답 확인:
  - GET /api/status → 200 OK `{"status":"ok"}`
  - GET /api/insuro/trend-insight/surge-events (인증 없이) → 401 `{"detail":"Missing or invalid authorization"}` (JWT 인증 정상 작동)
  - GET /api/insuro/trend-insight/categories (인증 없이) → 401 (기존 패턴 일관성 확인)
- 스크린샷: 해당없음 (API 백엔드 위주 작업, 프론트엔드 배포 후 확인 필요)

---

## 발견 이슈 및 해결

1. **season_calendar_check.py 미사용 변수**: `active_season_ids` 변수가 선언만 되고 사용되지 않음 → 제거 (커밋 f78220d)
2. **Worktree .env 부재**: worktree 디렉토리에 .env 파일이 없어서 스크립트가 Supabase 키를 찾지 못함 → 심볼릭 링크 생성
3. **TrendInsightTab TypeScript 경고**: IDE LSP가 실제로 사용 중인 변수에 대해 거짓 양성 보고 → npm run build 정상 통과로 확인

---

## 미처리 항목 (범위 외)

- DB 4테이블 실제 마이그레이션 실행: Supabase Management API로 SQL 실행 필요 (아누 실행)
- keywords → keyword_pool 초기 마이그레이션: DB 테이블 생성 후 실행
- 뉴스 크론 등록: `0 8,20 * * * ...` crontab 1줄 추가 필요
- Cloudflare 배포: PR 머지 후 배포

---

## Codex 사전 검증

- 실행 결과: FAIL (파일 미존재 — 구현 전이므로 당연)
- 설계 리스크 대응:
  - 급등 감지: keyword_trends에서 raw 증감률 직접 계산 (기존 surge_score 재사용 안 함) ✅
  - 시즌 임계값: surge_threshold_override 우선 → season_surge_threshold 폴백 ✅
  - keyword_pool/기존 수집 연계: Phase 2에서는 관리 테이블로만 사용 ✅

---

## 3 Step Why

**1st Why**: 고정 풀 한계로 풀 밖 급등 키워드를 놓침 → 뉴스 시그널 + 급등 감지 필요
**2nd Why**: 뉴스 API 무료/합법, SearchAd 게이트로 노이즈 차단, 시즌 캘린더는 정적 JSON → 비용/리스크 최소
**3rd Why**: API 복수 운용(약관 위반), LLM 예측(미검증), 커뮤니티 RSS(법적 리스크) 대비 채택안이 우월
→ A-B-C 논리적 일관성 확인 완료

---

## 머지 판단

- **머지 필요**: Yes
- **브랜치**: task/task-2329-dev3
- **워크트리 경로**: /home/jay/projects/InsuRo/.worktrees/task-2329-dev3
- **커밋 수**: 10개
- **머지 의견**: py_compile 전수 PASS, npm run build 성공, 서버 기동 + API 인증 정상. 기존 코드에 영향 없는 신규 파일 추가 위주. DB 마이그레이션은 SQL 파일만 생성 (실행은 별도). 충돌 가능성 낮음.

---

## 모델 사용 기록

| 팀원 | 모델 | 역할 | 정당성 |
|------|------|------|--------|
| 루(Lugh) | Sonnet | 백엔드 8개 MT | 일반 코딩, DB/API/스크립트 구현 |
| 브리짓(Brigid) | Sonnet | 프론트엔드 1개 MT | React UI 구현 |
| 다그다(Dagda) | Opus | 설계/검토/통합 | 팀장 판단/QC |

---

## 셀프 QC 체크리스트

- [x] 1. 영향 파일: 기존 main.py(엔드포인트 추가), run_trend_pipeline.sh(스텝 추가), TrendInsightTab.tsx(섹션 추가)
- [x] 2. 엣지 케이스: 빈 surge_events → UI 미표시, 빈 keyword_trends → 기준선 0 → 급등 미탐지 (정상)
- [x] 3. 작업 지시 일치: 10단계 구현 범위 모두 코드 작성 완료
- [x] 4. 에러 처리/보안: JWT 인증, 파라미터 검증, try-except, 블랙리스트 필터
- [x] 5. 테스트 커버: py_compile 4건, 드라이런 3건, 빌드 1건
- [x] 6. 이슈 모두 해결: 미사용 변수 1건 해결, .env 심링크 1건 해결
- [x] 7. 코드 아키텍처: 기존 스크립트 패턴(Supabase, dotenv, argparse, logging) 일관 적용
- [x] 8. 인터페이스 변경: surge-events API 신규 추가 (기존 API 미변경)
- [x] 11. 3문서 업데이트: plan.md → completed, checklist.md 체크, context-notes.md 3 Step Why 기록
- [x] 12. 3 Step Why: A-B-C 논리적 일관성 확인
- [x] 13. L1 스모크테스트: 서버 기동 + API 응답 확인

## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회


## 세션 통계
- 총 도구 호출: 0회

