# task-3048 — 구글 트렌드 수집 복구 (4개월 정지)

**레벨**: Lv.2 · **팀**: dev7-team · **회장 승인 완료** (2026-08-28)
**저장소**: `Jeon-Jonghyuk/InsuRo` (`/home/jay/projects/InsuRo`, 기본 브랜치 **main**)

## ★ 회장 제보
> "구글트렌드 기능 안 된다"
> 화면(`/keyword-analysis` → **구글 트렌드** 탭)에 **"최종 수집: 2026. 4. 29. 오후 10:53:31"** 로 4개월째 멈춰 있다.

---

## ANU 가 이미 규명한 것 (재조사 불필요 — 그대로 전제하라)

### 근인: 수집기를 아무도 부르지 않는다
```
server/trend_collector.py       158줄 · collect_trends() 존재 · pytrends 사용
  → 이 함수를 호출하는 코드가 저장소 어디에도 없다 (ANU grep 확인)

server/scripts/run_trend_pipeline.sh (cron 0 6 * * *)
  Step 0  season_calendar_check.py
  Step 1  daily_trend_collect.py       ← ★ 네이버 DataLab. 구글 아님
  Step 2  daily_saturation_collect.py
  Step 3  daily_ranking_calc.py
  Step 3.5 daily_surge_detect.py
  Step 4  daily_health_check.py
  → trend_collector 없음
```

### ★★ 두 트렌드를 혼동하지 마라 — 완전히 다른 시스템이다
```
① 네이버 DataLab  openapi.naver.com/v1/datalab/search
                  테이블 keyword_trends · keywords
                  상태 정상 (오늘 32,765건 수집)
                  t3019·t3026 이 손댄 것이 이쪽이다

② 구글 트렌드     pytrends
                  테이블 trend_data · trend_keywords
                  화면 POST /api/insuro/google-trends (main.py:2084)
                  상태 ★ 2026-04-30 이후 0건 — 이 태스크의 대상
```

### 구글 API 는 살아 있다 (ANU 실측)
```python
TrendReq(hl='ko', tz=540); build_payload(['암보험'], timeframe='today 3-m', geo='KR')
→ interest_over_time() 93행 수신. 최근값 {'암보험': 36}, {'암보험': 42, isPartial:True}
```
**차단이 아니다. 호출을 안 했을 뿐이다.**

### 현재 DB
```
trend_data       1,626행 · 최신 2026-04-30
trend_keywords     30행 · 활성 30개 · 최신 2026-04-23
pytrends         설치돼 있음
```

---

## 할 일

### ① 수집기를 파이프라인에 배선
`run_trend_pipeline.sh` 에 구글 트렌드 수집 단계를 추가한다.
- ★ **기존 Step 번호·순서를 흔들지 마라.** 뒤에 새 Step 으로 붙이는 것이 안전하다
- ★ **구글 실패가 네이버 파이프라인을 죽이면 안 된다.** 구글은 외부 API 이고 rate limit·차단이
  잦다. 실패해도 다른 Step 의 판정에 영향을 주지 않게 격리하라
- 로그를 `$LOGDIR` 규칙에 맞춰 남겨라(다른 Step 과 동일 형식)
- `trend_collector.py` 가 스크립트로 직접 실행 가능한지 확인하고, 아니면 진입점을 만들어라
  (`server/scripts/` 아래 얇은 러너 권장. `trend_collector.py` 본체 수정은 최소로)

### ② rate limit 방어
pytrends 는 구글 비공식 경로라 **429/차단이 쉽게 난다.** 활성 키워드 30개를 한 번에 돌리면 위험하다.
- 키워드 간 **간격(sleep)** 과 **배치 크기**를 두어라. 값은 근거와 함께 정하라
- 429·차단 시 **재시도 정책**을 두되 무한 재시도는 금지
- ★ 실패해도 **조용히 성공으로 보고하지 마라.** 몇 개 수집·몇 개 실패인지 드러나야 한다
  (이 조직에서 "0건인데 성공" 유형 사고가 반복됐다 — t3044 등)

### ③ 4개월 공백 처리 — 소급 수집은 하지 마라
- ★ **지금부터 수집**만 한다. 과거 4개월 소급은 **이번 범위가 아니다**
- pytrends `timeframe` 기본값을 무엇으로 할지 정하고 근거를 남겨라
  (`today 3-m` 이면 최근 3개월이 한 번에 들어와 공백 상당분이 자연히 메워질 수 있다 — 확인하라)
- 소급이 필요하다고 판단되면 **설계만 제안**하고 ANU 판단을 받아라

### ④ 화면에서 실제로 보이는지 확인
```
POST /api/insuro/google-trends   main.py:2084
  → trend_keywords 에서 키워드 id 조회 → trend_data 에서 date·value·related_queries_json 조회
```
수집 후 이 API 가 **최신 데이터를 반환**하는지 확인하라. DB 에만 들어가고 화면이 옛 값을 보면 의미 없다.

---

## ★ 하지 말 것
- **네이버 DataLab 경로 변경 금지** — `daily_trend_collect.py` · `keyword_trends` · `keywords`
  (t3019·t3026 결과물. 오늘 정상 동작 확인됨)
- `daily_health_check.py` · `daily_ranking_calc.py` · `daily_saturation_collect.py` 변경 금지
- `alert_notify.py` 변경 금지 (t3008 결과물)
- **과거 4개월 소급 수집 실행 금지** (설계 제안만)
- **trend_data 기존 1,626행 삭제·변경 금지**
- 자격증명 값을 저장소에 커밋

## allowed_resources
```yaml
allowed_resources:
  paths:
    - "server/trend_collector.py"
    - "server/scripts/run_trend_pipeline.sh"
    - "server/scripts/collect_google_trends.py"
    - "server/scripts/tests/**"
    - "server/tests/**"
    - "memory/reports/task-3048.md"
  forbidden_paths:
    - "server/scripts/daily_trend_collect.py"
    - "server/scripts/daily_health_check.py"
    - "server/scripts/daily_ranking_calc.py"
    - "server/scripts/daily_saturation_collect.py"
    - "server/scripts/alert_notify.py"
    - "server/main.py"
    - "src/**"
    - "extension/**"
    - ".github/workflows/**"
  commands: ["python3", "pytest", "bash", "gh"]
  merge_policy: "tiered"
  ttl_hours: 24
```

## 검증 (실측 강제)
1. **실 수집 1회** — 실제로 구글에서 받아 `trend_data` 에 들어가는지.
   ★ **몇 개 키워드 · 몇 행**이 들어갔는지 숫자로. 목업 금지
2. **최신 데이터 확인** — `trend_data` 의 `max(collected_at)` 이 오늘로 갱신되는지
3. **화면 API 확인** — `POST /api/insuro/google-trends` 가 최신 값을 반환하는지.
   실제 응답을 보고서에 붙여라
4. **rate limit 내성** — 30개 키워드 전체를 돌렸을 때 429·차단이 나는지, 나면 어떻게 처리되는지
5. **격리 확인** — 구글 수집이 실패해도 **네이버 파이프라인 Step 판정이 영향받지 않는지**
6. **실패 표면화** — 0건 수집 시 성공으로 보고되지 않는지
7. **회귀** — `pytest` **base 재측정 기준선** (현재 main 기준 2,878 passed / 5 failed —
   그 5건은 `.env` 유무에 반응하는 환경 의존 테스트로 base 에서도 동일하게 실패한다.
   신규 실패 0건이면 통과다)
8. **봉인** — 수집 0건을 성공으로 처리하는 변이를 만들어 테스트가 FAIL 하는지 확인·복원.
   변이가 no-op 이 아님을 `assert` 로 먼저 증명하라

## ★ 실행 시 주의
- 구글에 과도한 요청을 보내지 마라. **IP 차단되면 복구가 어렵다**
- 검증은 **소수 키워드**로 하고, 전체 30개 실행은 신중히 1회만
- cron 실행 시각(06:00 KST)과 겹치지 않게 하라

## 완료 조건 (DoD)
**구글 트렌드가 파이프라인에서 실제로 수집되어 `trend_data` 가 오늘 날짜로 갱신되고,
화면 API 가 최신 값을 반환하며, 구글 실패가 네이버 파이프라인을 죽이지 않는다.**

## ★ 세션 조기 종료 대책
시작 즉시 브랜치 + 드래프트 PR 을 먼저 열어라. **단계마다 커밋하라.**
★ ANU 명세 전제가 틀렸다고 판단되면 구현하지 말고 **반증을 먼저 기록한 뒤 보고하라.**

## 운영 계약
- `origin/main` 기준 `git pull --ff-only` 후 시작
- ★ **worktree 를 써라.** 메인 저장소는 cron 이 매일 06:00·08:00 에 직접 실행한다
- ★ cron 은 **디스크 파일**을 직접 실행한다. 머지만으로는 반영되지 않는다(반영은 ANU 가 한다)
- ★ `gh` 호출 시 `GH_TOKEN="$BOT_GITHUB_TOKEN"` 주입 필수 (회장 개인 PAT 금지 — 감사기록 오염)
- 워크플로우 `/home/jay/workspace/prompts/DIRECT-WORKFLOW.md` · QC `/home/jay/workspace/teams/shared/QC-RULES.md`
- `WORKSPACE_ROOT=/home/jay/workspace` · `CHAT_ID=6937032012` · 수집자 key `ANU_KEY=c119085addb0f8b7`
- 완료 경로는 `finish-task.sh` 실행이 유일하다. 수동 `.done` 금지.

## 보고
**PR 생성까지가 범위다. 머지는 ANU 가 한다. 자동 머지 금지.**
`memory/reports/task-3048.md` 작성 후 표준 완료 콜백 등록. 콜백 프롬프트 **UTF-8 3900 bytes 이하**.
★ 봉투 첫 줄에 **"실 수집 행수 + 화면 API 최신값 반환 여부"** 를 담아라.