# Agent 미팅: InsuWiki 키워드 트렌드 시스템 — Cycle 4~5 (발산 심화)

**날짜**: 2026-04-23
**안건**: 설계사 검색 키워드 Top 100 시스템 — 미해결 쟁점 심화 + 원래 질문 재점검
**참여 페르소나**: 헤르메스, 불칸, 이리스, 아테나, 아르고스, 로키, 마아트, 비너스, 아틀라스, 다빈치 (10명)
**기반**: Cycle 1~3 핵심 발산 결과

---

## Cycle 1~3 요약 (기반 정보)

1. Layer 2 소스: 네이버 검색광고 API(공식) + 자동완성(비공식) + 관련검색어. 주 1회 수집
2. Layer 3: user_search_log 테이블, SHA-256 해시, unique_users 기준, 주간 30건 미만 시 비활성화
3. 카테고리 필터링: 보험 도메인 사전 300개 + 네거티브 키워드 + 관리자 승인 큐
4. 데이터 보존: 영구 보존, active/inactive/retired 3상태, 6개월 retired
5. UX: TOP 20 기본 뷰, Layer별 컬러 태그, 신뢰도 3단계 인디케이터
6. 모듈화: BaseCollector 추상 + FixedCollector/NaverCollector/InsuroLogCollector
7. 다빈치 대안: Search Console 역추적으로 Layer 2 교체
8. 다빈치 예측: 계절성 기반 "키워드 레이더" — 다음 달 급상승 예상 5개

---

## Cycle 4: 미해결 쟁점 심화

### 쟁점 1: Layer 2를 네이버 공식 API 단독으로 갈 것인가, Search Console 역추적을 Layer 2B로 추가할 것인가?

---

#### 헤르메스 (백엔드/인프라)

네이버 검색광고 API는 월별 검색량만 제공하고 일별 추이를 주지 않습니다. Search Console은 일별 클릭/노출을 줍니다. 데이터 성격이 다르므로 대체가 아니라 보완입니다. 구현 관점에서 Search Console API는 google-auth + oauth2 토큰 관리가 추가로 필요합니다. NaverCollector와 SearchConsoleCollector를 BaseCollector 하위에 병렬로 두고, 스코어링 시 각 소스 가중치를 별도로 적용하는 설계가 맞습니다. 다만 Phase 1에서 두 개 동시 구현은 범위 과잉이므로, Layer 2A(네이버)만 Phase 1, Layer 2B(Search Console)는 Phase 2로 분리해야 합니다.

#### 불칸 (백엔드 구현)

Search Console API의 실질적 제약을 짚겠습니다. 첫째, InsuWiki가 구글 검색에 노출되는 키워드만 수집 가능합니다. 인덱싱되지 않은 키워드는 아예 잡히지 않습니다. 둘째, 데이터 지연이 48~72시간입니다. 셋째, 일일 API 호출 한도가 25,000건이지만 키워드 100개 수준에서는 문제가 없습니다. 결론적으로 Search Console은 "InsuWiki에 사용자가 유입되는 실제 경로"를 보여주므로 설계사 관점에서 더 실용적이지만, InsuWiki 서비스가 구글 노출이 충분해야 의미가 있습니다. 현재 InsuWiki의 구글 인덱싱 페이지 수를 먼저 확인해야 합니다.

#### 이리스 (프론트엔드)

UI 관점에서 Layer 2A와 2B를 사용자에게 어떻게 구분해서 보여줄지가 관건입니다. "네이버 트렌드"와 "구글 유입" 탭을 별도로 만들 것인지, 통합 스코어로 합칠 것인지. 설계사 입장에서는 출처 구분보다 "어떤 키워드가 뜨고 있는가"만 중요하므로, 통합 스코어가 낫습니다. Layer별 컬러 태그에 소스 구분까지 추가하면 인디케이터가 과밀해집니다. 소스 정보는 키워드 상세 뷰에서만 펼쳐 보여주는 Progressive Disclosure 방식을 권장합니다.

#### 아테나 (전략/분석)

Layer 2B를 추가하면 스코어링 공식이 복잡해집니다. 현재 Layer 2A 단독이면 네이버 검색량 단일 변수인데, 2B가 들어오면 "네이버 검색량 vs 구글 클릭수"를 정규화해서 합산해야 합니다. 두 플랫폼의 스케일이 완전히 다릅니다 (네이버 월 10만 vs 구글 일 50클릭). 정규화 공식 없이 합치면 한쪽이 묻힙니다. Phase 1에서는 Layer 2A 단독이 올바르며, Phase 2에서 정규화 공식을 설계한 뒤 2B를 추가하는 것이 순서입니다.

#### 아르고스 (테스트/검증)

Search Console 데이터의 검증 방법이 문제입니다. 네이버 API는 공식 수치이므로 ground truth로 쓸 수 있지만, Search Console 데이터는 InsuWiki가 노출된 쿼리만 보여줍니다. 이 데이터가 "보험 시장 전체 트렌드"를 대표하는지 검증할 방법이 없습니다. 표본 편향이 심하다면 스코어링을 오히려 왜곡합니다. 2B 도입 전 최소 4주간 데이터를 수집해서 Layer 2A와의 상관관계를 측정하는 파일럿이 필수입니다.

#### 로키 (레드팀)

Layer 2B 추가 논의 자체가 시기상조입니다. Layer 2A조차 아직 구현되지 않았습니다. 구현 전에 소스를 두 개로 늘리는 설계를 확정하면, 실제 데이터를 보지도 않고 정규화 공식을 짜야 합니다. 이론적으로는 맞지만 데이터 없이 짠 공식은 100% 수정됩니다. Layer 2A를 먼저 4주 운영하고, 실제 데이터 분포를 확인한 뒤에 2B 추가 여부를 판단하는 것이 합리적입니다. 지금 결정할 것은 "2B는 Phase 2에서 검토한다" 한 문장이면 됩니다.

#### 마아트 (품질/검증)

BaseCollector 추상 클래스의 인터페이스가 2B를 수용할 수 있는지 지금 확인해둬야 합니다. 로키 말처럼 구현은 Phase 2로 미루되, collect() 메서드의 반환 스키마가 Search Console 데이터 형태(클릭수, 노출수, CTR, 평균 순위)를 담을 수 있어야 합니다. 지금 NaverCollector만 보고 인터페이스를 짜면 Phase 2에서 BaseCollector를 깨뜨려야 합니다. 최소한 반환 타입에 optional 필드를 확보해두는 설계가 필요합니다.

#### 비너스 (UX/마케팅)

설계사 관점에서 "이 키워드가 네이버에서 뜨는지 구글에서 뜨는지"는 관심사가 아닙니다. 설계사가 원하는 것은 "지금 고객들이 뭘 검색하고 있는가"입니다. 따라서 소스 구분은 내부 로직일 뿐 UX에 노출할 필요가 없습니다. 하나의 "인기도 점수"로 통합하고, 데이터 출처는 어드민 대시보드에서만 확인 가능하게 하면 됩니다. 설계사 화면은 단순해야 합니다.

#### 아틀라스 (인프라/확장)

Search Console API 인증은 서비스 계정(Service Account) 방식으로 처리하면 oauth2 토큰 관리 부담이 줄어듭니다. InsuWiki의 Search Console 소유권이 이미 확인되어 있다면 Service Account에 읽기 권한만 부여하면 됩니다. 인프라 관점에서 추가 부담은 크지 않지만, 일별 수집 배치에 네이버 + 구글 두 소스가 들어가면 수집 시간이 늘어납니다. systemd timer를 소스별로 분리하는 것을 권장합니다.

#### 다빈치 (혁신/대안)

Search Console 역추적의 진짜 가치는 "키워드 발견"입니다. 네이버 API는 우리가 키워드를 지정해야 검색량을 알려줍니다. Search Console은 우리가 모르는 키워드를 역으로 알려줍니다. 이것은 Layer 1(고정)이나 Layer 2A(지정 검색)와 근본적으로 다른 "발견(Discovery)" 메커니즘입니다. Layer 2B가 아니라 "Layer 2.5: Discovery Layer"로 별도 포지셔닝하면 3-Layer 구조를 깨뜨리지 않고 확장할 수 있습니다.

---

**쟁점 1 잠정 합의**: Layer 2는 Phase 1에서 네이버 API(2A) 단독. Search Console은 Phase 2에서 "Discovery Layer"로 검토. 단, Phase 1의 BaseCollector 인터페이스 설계 시 Search Console 데이터 형태를 수용할 수 있도록 반환 타입에 여유를 둔다.

---

### 쟁점 2: 보험 도메인 사전 300개 초기 구축 — 누가, 어떻게?

---

#### 헤르메스 (백엔드/인프라)

사전 300개를 처음부터 수작업으로 만드는 것은 비효율적입니다. 자동화 가능한 소스가 있습니다. (1) InsuWiki의 기존 위키 문서 제목 추출 — 보험 용어가 이미 체계적으로 정리되어 있음. (2) 네이버 검색광고 API의 연관 키워드 기능 — "보험"으로 시작하여 확장. (3) 보험업계 표준 용어집(금융감독원 보험용어사전). 이 세 소스를 합치면 300개 이상을 자동 수집할 수 있고, 사람이 할 일은 검수와 카테고리 분류뿐입니다.

#### 불칸 (백엔드 구현)

구체적인 구현 방안을 제시합니다. Python 스크립트 하나로 seed_dictionary.py를 작성합니다. Step 1: InsuWiki Supabase에서 wiki_pages 테이블의 title 컬럼 전체 추출 → 보험 관련 명사 필터링. Step 2: 네이버 검색광고 API에 "보험", "보장", "보상" 등 시드 5개를 넣고 연관 키워드 각 50개씩 추출. Step 3: 중복 제거 + 정규화(띄어쓰기, 대소문자). Step 4: CSV 출력 → 사람이 검수 → Supabase INSERT. 예상 소요: 스크립트 반나절 + 검수 반나절 = 1일.

#### 이리스 (프론트엔드)

사전 관리를 위한 어드민 UI가 필요합니다. 단순 텍스트 파일이나 DB 직접 편집으로는 유지보수가 안 됩니다. 최소한 키워드 추가/삭제/카테고리 변경/활성화 토글 기능이 있는 관리 화면이 필요합니다. 다만 Phase 1에서는 CSV 업로드 방식으로 충분하고, 관리 UI는 Phase 2입니다.

#### 아테나 (전략/분석)

300개의 카테고리 분류 체계가 중요합니다. 보험 도메인은 (1) 상품명(실비보험, 암보험 등), (2) 행동 키워드(보험비교, 보험료계산), (3) 상황 키워드(교통사고 보험, 여행자보험), (4) 감정/의도 키워드(보험 해약 고민, 보험 추천 받고 싶다)로 나뉩니다. 단순히 300개를 나열하는 것이 아니라 이 4개 카테고리별 비중을 의도적으로 설계해야 합니다. 상품명 120개, 행동 80개, 상황 60개, 감정/의도 40개를 제안합니다.

#### 아르고스 (테스트/검증)

사전의 품질 검증 방법을 정의해야 합니다. 300개 중 보험과 무관한 키워드가 섞이면 트렌드 결과가 오염됩니다. 검증 기준: (1) 각 키워드로 네이버 검색 시 첫 페이지에 보험 관련 결과가 50% 이상인지 확인. (2) 금융감독원 보험용어사전에 존재하는지 교차 확인. (3) InsuWiki에 해당 주제의 문서가 존재하는지 확인. 3가지 중 2가지 이상 충족하면 PASS. 이 검증은 자동화 가능합니다.

#### 로키 (레드팀)

300개라는 숫자의 근거가 없습니다. 왜 300인가요? 200이면 부족하고 500이면 과다한 이유는? "보험 관련 키워드를 모두 포괄하면서 관리 가능한 규모"라는 모호한 기준밖에 없습니다. 차라리 처음에 100개로 시작하여 Layer 3(사용자 검색 로그)에서 유입되는 신규 키워드를 점진적으로 추가하는 성장형 사전이 낫습니다. 300개를 한꺼번에 만들면 사용되지 않는 키워드가 절반 이상일 것입니다.

#### 마아트 (품질/검증)

사전의 버전 관리가 필요합니다. 키워드 추가/삭제 이력이 없으면 "언제, 왜 이 키워드가 추가됐는지" 추적이 안 됩니다. keyword_dictionary 테이블에 created_at, deprecated_at, reason 필드를 포함하고, 변경 시 audit log를 남겨야 합니다. 사전 변경이 트렌드 결과에 미치는 영향을 소급 분석하려면 이 이력이 필수입니다.

#### 비너스 (UX/마케팅)

설계사가 실제로 사용하는 용어와 업계 공식 용어가 다를 수 있습니다. 예를 들어 공식 명칭은 "실손의료보험"이지만 설계사와 고객은 "실비보험"이라고 합니다. 사전에 공식 용어만 넣으면 실제 검색 패턴을 못 잡습니다. 동의어/약어 매핑을 포함해야 합니다. "실손의료보험 = 실비보험 = 실손보험"처럼요. 이 매핑은 검색량 합산에도 활용됩니다.

#### 아틀라스 (인프라/확장)

사전이 커지면 네거티브 키워드 필터링의 성능이 중요해집니다. 300개 수준에서는 단순 해시맵 lookup으로 충분하지만, 1000개 이상으로 성장하면 Trie 구조나 Bloom filter 도입을 검토해야 합니다. 다만 이것은 Phase 3 이후의 문제이므로 지금은 해시맵으로 시작합니다.

#### 다빈치 (혁신/대안)

사전 300개를 사람이 만드는 대신, LLM에게 "보험 도메인에서 설계사와 고객이 검색할 만한 키워드 300개를 카테고리별로 생성해줘"라고 시키면 10분이면 됩니다. 물론 LLM 생성 키워드는 환각 위험이 있으므로 아르고스의 3가지 검증 기준으로 필터링합니다. 이 방법이 수작업 대비 10배 빠르고, 사람이 놓치는 롱테일 키워드도 잡을 수 있습니다.

---

**쟁점 2 잠정 합의**: 3단계 접근. (1) LLM + InsuWiki 문서 제목 + 네이버 연관 키워드로 후보 500개 자동 생성. (2) 아르고스 검증 기준 3가지로 자동 필터링. (3) 사람이 최종 검수하여 초기 150개로 시작 (로키 의견 반영, 300개에서 축소). Phase 1 운영 4주 후 Layer 3 데이터 기반으로 점진 확장. 동의어/약어 매핑 포함(비너스). 버전 관리 audit log 포함(마아트).

---

### 쟁점 3: 동적 슬롯 배분(Layer 3 비활성 시 50→70) 구현 복잡도 vs 단순 고정 배분

---

#### 헤르메스 (백엔드/인프라)

동적 슬롯의 구현 복잡도를 구체적으로 분석합니다. 현재 합의된 배분: Layer 1(고정) 30슬롯 + Layer 2(네이버) 50슬롯 + Layer 3(사용자) 20슬롯 = 100. Layer 3 비활성 시 20슬롯을 Layer 2에 할당하면 70이 됩니다. 구현은 단순합니다 — `get_slot_allocation()` 함수에 Layer 3 활성 여부를 파라미터로 넣고 조건 분기. 코드 5줄 수준입니다. 복잡도 문제가 아니라, "20슬롯을 어디에 배분하느냐"의 정책 문제입니다.

#### 불칸 (백엔드 구현)

구현 코드를 구체적으로 보여드립니다. `def allocate_slots(layer3_active: bool) -> dict: if layer3_active: return {"L1": 30, "L2": 50, "L3": 20} else: return {"L1": 30, "L2": 70, "L3": 0}` — 이게 전부입니다. 동적 배분이라고 해서 ML 모델이나 실시간 조정이 아닙니다. binary 스위치입니다. 다만 "Layer 3 활성 기준"이 "주간 unique_users 30건 이상"인데, 이 임계값 자체가 변경될 수 있으므로 config로 빼야 합니다.

#### 이리스 (프론트엔드)

동적 배분이든 고정 배분이든 프론트엔드에 영향이 없습니다. 프론트는 "Top 100 키워드 목록"만 받으면 됩니다. 각 키워드가 어느 Layer에서 왔는지는 메타 데이터로 표시하되, 슬롯 수가 바뀌는 것은 백엔드 내부 로직입니다. UI에 "현재 Layer 3 비활성"을 표시할지 여부만 결정하면 됩니다. 표시한다면 작은 배너로 "사용자 검색 데이터 수집 중 (4주 후 활성화 예정)" 정도.

#### 아테나 (전략/분석)

동적 배분의 실질적 의미를 따지면, Phase 1에서 Layer 3은 무조건 비활성입니다. 사용자 검색 로그가 쌓이기 전까지 Layer 3은 빈 상태입니다. 따라서 Phase 1은 자동으로 L1:30 + L2:70 배분입니다. Layer 3이 활성화되는 시점은 Phase 3 이후인데, 그때 가서 배분 비율을 조정해도 늦지 않습니다. Phase 1에서 동적 배분 로직을 구현하는 것은 YAGNI(You Ain't Gonna Need It)입니다.

#### 아르고스 (테스트/검증)

동적 배분을 도입하면 테스트 매트릭스가 2배 늘어납니다. Layer 3 활성/비활성 두 상태를 모두 테스트해야 합니다. 고정 배분이면 단일 상태만 테스트합니다. 코드 복잡도는 낮지만 테스트 복잡도가 올라갑니다. Phase 1에서는 고정 배분(L1:30 + L2:70)으로 시작하고, Phase 3에서 Layer 3 추가 시 동적 배분 로직과 함께 테스트를 확장하는 것이 효율적입니다.

#### 로키 (레드팀)

"코드 5줄이니까 간단하다"는 함정입니다. 코드는 5줄이지만, 이 5줄이 만드는 상태 전이(L3 비활성→활성, 활성→비활성)와 그에 따른 Top 100 목록 변동은 사용자에게 혼란을 줍니다. 어제까지 Top 100에 있던 키워드가 오늘 갑자기 빠지는 경험. "왜 내가 추적하던 키워드가 사라졌지?" Layer 3이 활성화되면서 Layer 2의 하위 20개가 밀려나기 때문인데, 사용자는 이걸 이해할 수 없습니다. 고정 배분이 UX를 안정시킵니다.

#### 마아트 (품질/검증)

로키 의견에 동의합니다. 추가로, "주간 unique_users 30건"이라는 임계값이 경계에서 진동할 수 있습니다. 29명→활성→31명→비활성→28명 같은 패턴이면 매주 배분이 바뀝니다. 히스테리시스(hysteresis)를 적용해야 합니다 — 활성화 임계값 30, 비활성화 임계값 20. 이렇게 하면 경계 진동은 방지되지만, 구현 복잡도가 또 올라갑니다. Phase 1에서는 불필요합니다.

#### 비너스 (UX/마케팅)

설계사 관점에서 Top 100 목록의 안정성이 중요합니다. 매주 목록이 크게 바뀌면 "이 기능은 불안정하다"는 인상을 줍니다. 동적 배분은 목록 변동 폭을 키우므로 초기 사용자 신뢰 구축에 해롭습니다. Phase 1은 고정 배분으로 안정적인 경험을 제공하고, Layer 3이 충분한 데이터를 축적한 Phase 3에서 점진적으로 슬롯을 할당하는 것이 UX적으로 건전합니다.

#### 아틀라스 (인프라/확장)

동적 배분의 인프라 영향은 미미합니다. DB 쿼리에서 LIMIT 절 값이 바뀌는 정도입니다. 다만 캐싱을 도입한다면 (Top 100을 Redis에 캐시), 배분 변경 시 캐시 무효화 로직이 추가됩니다. 고정 배분이면 캐시 TTL만 관리하면 됩니다. Phase 1 고정 배분 + Phase 3 동적 배분 전환에 동의합니다.

#### 다빈치 (혁신/대안)

동적 배분 대신 "유동 풀(Fluid Pool)" 개념을 제안합니다. Layer별 슬롯을 고정하지 말고, 전체 100개를 단일 풀로 두되, 스코어링 시 Layer 가중치만 조절합니다. Layer 1 가중치 x2, Layer 2 가중치 x1.5, Layer 3 가중치 x1. 이렇게 하면 슬롯 배분 문제 자체가 사라지고, 스코어가 높은 순서대로 100개를 뽑으면 됩니다. Layer 3 데이터가 없으면 자연스럽게 Layer 1, 2 키워드만 올라옵니다.

---

**쟁점 3 잠정 합의**: Phase 1에서는 고정 배분(L1:30 + L2:70). Layer 3은 Phase 3에서 도입. 다빈치의 "유동 풀" 개념은 Phase 3 설계 시 검토 후보로 보존. 로키/마아트의 UX 안정성 + 히스테리시스 복잡도 우려를 수용. 동적 배분 구현은 Phase 3으로 연기.

---

### 쟁점 4: 스코어링 가중치 — 네이버 검색량 vs unique_users vs 구글 트렌드 값

---

#### 헤르메스 (백엔드/인프라)

스코어링 공식을 구체화합니다. Phase 1에서 사용 가능한 변수: (1) 네이버 월간 검색량(L2A), (2) 구글 트렌드 상대지수(기존 InsuRo 파이프라인에서 이미 수집 중). Phase 3에서 추가: (3) InsuWiki unique_users 검색 횟수(L3). 공식 제안: `score = 0.6 * normalize(naver_volume) + 0.4 * normalize(google_trend)`. L3 활성 시: `score = 0.4 * naver + 0.3 * google + 0.3 * unique_users`. normalize는 min-max 정규화(0~100 스케일).

#### 불칸 (백엔드 구현)

정규화 방법이 핵심입니다. 네이버 검색량은 절대값(예: 월 45,000), 구글 트렌드는 상대지수(0~100), unique_users는 건수(예: 주간 50명). 단순 min-max 정규화는 이상치에 취약합니다. "실비보험" 검색량이 월 50만인데 나머지가 1만 이하이면, 실비보험만 100이고 나머지는 전부 20 이하로 뭉칩니다. 로그 정규화 `log(1 + volume)`를 먼저 적용한 뒤 min-max를 하면 분포가 고르게 펴집니다.

#### 이리스 (프론트엔드)

스코어를 사용자에게 어떻게 표시할지가 UX의 핵심입니다. 숫자 점수(87.3점)는 비직관적입니다. 신뢰도 인디케이터처럼 3단계(상승/유지/하락)로 단순화하거나, 검색량 크기를 막대 차트로 시각화하는 것이 설계사에게 유용합니다. 내부 스코어링은 정밀하게 하되, 표시는 단순하게. "인기도 상/중/하" + "추세 화살표(상승/하락/유지)" 조합을 제안합니다.

#### 아테나 (전략/분석)

가중치를 고정하지 말고, A/B 테스트 가능한 config로 두어야 합니다. Phase 1에서 0.6/0.4로 시작하되, 설계사들이 실제로 어떤 키워드를 클릭하고 상세 조회하는지 사용 로그를 분석하여, "사용 행동"과 "스코어 순위"의 상관관계를 측정합니다. 상관관계가 낮으면 가중치를 조정합니다. 이 피드백 루프가 스코어링 품질의 핵심입니다.

#### 아르고스 (테스트/검증)

스코어링 공식의 테스트 방법: (1) 알려진 인기 키워드 10개가 Top 20 안에 포함되는지 확인(recall 테스트). (2) 명백히 비인기인 키워드가 Top 50 밖에 있는지 확인(precision 테스트). (3) 가중치를 극단값(1.0/0.0, 0.0/1.0)으로 바꿔도 결과가 합리적인지 확인(robustness 테스트). 이 테스트를 자동화하여 가중치 변경 시마다 실행합니다.

#### 로키 (레드팀)

스코어링 가중치 논쟁은 데이터 없이 공회전하고 있습니다. "0.6 vs 0.4"나 "0.5 vs 0.5"나 실제 데이터를 돌려보기 전에는 순수한 추측입니다. Phase 1에서는 네이버 검색량 단일 변수 순위로 가세요. 구글 트렌드를 합산하면 두 소스의 정규화 문제가 바로 터집니다. 단일 변수면 순위가 직관적이고 설명 가능합니다. "이 키워드가 왜 3위인가? 네이버 검색량 월 45,000이니까." 두 변수 합산이면 "왜 3위인가?"에 대한 답이 "네이버 30점 + 구글 28점 = 58점"인데, 이 58점이 뭘 의미하는지 아무도 모릅니다.

#### 마아트 (품질/검증)

로키 의견에 부분 동의합니다. 단일 변수 순위의 장점은 검증 가능성입니다. 설계사에게 "이 순위가 맞나요?"라고 물었을 때, 단일 변수면 직관적으로 판단할 수 있지만, 합산 점수면 판단이 불가능합니다. 다만 네이버 검색량만으로는 "계절성 급상승"을 잡을 수 없습니다(월별 데이터라서 반응이 느림). 구글 트렌드의 일별 데이터가 "급상승 감지"에 필요합니다. 따라서 순위는 네이버 검색량 기준으로 하되, "급상승 키워드" 태그는 구글 트렌드 데이터로 별도 표시하는 이원 체계를 제안합니다.

#### 비너스 (UX/마케팅)

마아트의 이원 체계가 UX적으로 가장 깔끔합니다. 설계사 화면에서 "인기 키워드 Top 100"은 네이버 검색량 순위, "급상승 키워드"는 구글 트렌드 변동률 기반으로 별도 섹션. 이렇게 하면 "안정적인 인기 키워드"와 "지금 뜨는 키워드"를 동시에 제공하면서도 스코어링 혼란이 없습니다. 설계사가 원하는 두 가지 정보("항상 인기인 것"과 "갑자기 뜨는 것")를 명확히 분리합니다.

#### 아틀라스 (인프라/확장)

이원 체계이면 DB 쿼리가 단순해집니다. Top 100은 `ORDER BY naver_volume DESC LIMIT 100`, 급상승은 `ORDER BY trend_change_rate DESC LIMIT 10`. 합산 스코어링이면 매번 두 소스를 JOIN해서 계산해야 합니다. 캐싱 전략도 이원 체계가 유리합니다 — 각각 별도 TTL로 관리할 수 있습니다.

#### 다빈치 (혁신/대안)

이원 체계에 한 가지를 추가합니다. "급상승 예측" — 과거 3년간 동일 시기 데이터를 분석하여 "다음 달에 급상승할 것으로 예상되는 키워드 5개"를 보여줍니다. Cycle 3에서 제안한 "키워드 레이더" 개념입니다. 이건 Phase 2 이후이지만, 데이터 수집은 Phase 1부터 시작해야 합니다 (과거 데이터 적재). InsuRo의 구글 트렌드 파이프라인에서 이미 수집 중인 데이터를 InsuWiki 쪽에서 참조하면 추가 수집 없이 가능합니다.

---

**쟁점 4 잠정 합의**: Phase 1 스코어링은 이원 체계 채택. (1) 인기 순위: 네이버 월간 검색량 단일 변수. (2) 급상승 태그: 구글 트렌드 주간 변동률. 합산 스코어링은 Phase 3에서 Layer 3 데이터 확보 후 검토. 가중치는 config로 외부화하여 A/B 테스트 가능하게 준비(아테나). 로그 정규화 적용(불칸). "키워드 레이더"(다빈치)는 Phase 2 검토 후보.

---

## Cycle 5: 제이회장님 원래 질문 재점검

### 질문 1: "리스트에 없는 키워드 검색 시 안내 문구" — 구체적 문구와 UX 흐름

---

#### 헤르메스 (백엔드/인프라)

API 레벨에서 처리합니다. `/api/keyword-trend/search?q=XXX` 엔드포인트에서 키워드가 dictionary에 없으면 404가 아니라 200 + 안내 메시지를 반환합니다. `{"found": false, "message": "...", "suggestions": [...]}`. suggestions에는 입력 키워드와 유사한 사전 내 키워드 3개를 Levenshtein distance 또는 음절 매칭으로 추출하여 제공합니다. "실비보헌" 입력 시 → "실비보험"을 suggestions로 제안.

#### 불칸 (백엔드 구현)

유사 키워드 추출의 구현은 fuzzywuzzy 또는 python-Levenshtein 라이브러리로 즉시 가능합니다. 사전 150개 수준이면 전수 비교해도 1ms 이내입니다. 한국어 초성 검색도 추가하면 편의성이 올라갑니다. "ㅅㅂㅂㅎ" → "실비보험" 매칭. 이건 jamo 라이브러리로 구현 가능합니다.

#### 이리스 (프론트엔드)

구체적인 UX 흐름을 설계합니다. (1) 검색창에 키워드 입력 → 자동완성 드롭다운에 매칭 키워드 표시. (2) 매칭 키워드가 없을 때: 드롭다운에 "해당 키워드는 아직 트렌드 데이터가 없습니다" 메시지 + "유사 키워드: 실비보험, 실손보험" 추천 링크. (3) 추천 링크 클릭 시 해당 키워드 트렌드로 이동. (4) 검색 데이터가 아예 없는 키워드도 "관심 키워드로 등록" 버튼을 제공하여 Phase 3의 사용자 키워드 수요 데이터로 활용. 화면에는 빈 차트 대신 일러스트레이션 + 안내 텍스트를 표시합니다.

#### 아테나 (전략/분석)

"관심 키워드로 등록" 기능은 전략적으로 매우 중요합니다. 사용자가 검색했지만 데이터가 없는 키워드는 곧 "사전에 빠진 수요"입니다. 이 데이터를 수집하면 사전 확장의 근거가 됩니다. 주간으로 "미등록 검색어 Top 10"을 집계하면, 어떤 키워드를 사전에 추가할지 데이터 기반으로 결정할 수 있습니다.

#### 아르고스 (테스트/검증)

안내 문구의 A/B 테스트 대상을 정의합니다. 문구 A: "해당 키워드는 아직 트렌드 데이터가 없습니다." 문구 B: "'OO보험'의 트렌드 데이터를 준비 중입니다. 유사한 키워드를 확인해보세요." 측정 지표: (1) 유사 키워드 클릭률, (2) 이탈률, (3) "관심 키워드 등록" 전환율. B가 더 능동적이어서 이탈률이 낮을 것으로 예상합니다.

#### 로키 (레드팀)

"관심 키워드로 등록" 기능은 스팸 벡터입니다. 봇이 무의미한 키워드를 대량 등록하면 미등록 검색어 집계가 오염됩니다. rate limiting(IP당 일 10건)과 최소 문자 수(2자 이상) 검증이 필수입니다. 또한 비인증 사용자의 등록은 차단해야 합니다.

#### 마아트 (품질/검증)

안내 문구에 "데이터가 없습니다"라고 하면 서비스 품질에 대한 부정적 인식을 줄 수 있습니다. "현재 OO 키워드의 트렌드를 분석 중입니다"처럼 진행형 표현이 UX 품질을 높입니다. 거짓말이 아닌 범위에서요 — 실제로 미등록 검색어를 모니터링하여 수요가 확인되면 사전에 추가할 것이니까요.

#### 비너스 (UX/마케팅)

최종 문구 제안: 주 문구는 "'{키워드}'의 트렌드 데이터를 준비 중입니다." 부 문구는 "이런 키워드는 어떠세요?" + 유사 키워드 3개 칩. CTA 버튼: "이 키워드 알림 받기" (관심 등록). 빈 상태 일러스트: 돋보기 + 그래프 아이콘 조합. 톤은 "아직 없다"가 아니라 "곧 준비된다"로.

#### 아틀라스 (인프라/확장)

미등록 검색어 로깅용 테이블을 추가합니다. `keyword_requests(id, keyword, user_id, requested_at)`. 이 테이블은 Phase 3의 사전 확장 데이터 소스로 활용됩니다. 주간 배치로 TOP 10을 추출하는 materialized view를 만들면 어드민 대시보드에서 바로 조회 가능합니다.

#### 다빈치 (혁신/대안)

한 걸음 더 나아가서, 미등록 키워드에 대해 즉석으로 네이버 검색량을 실시간 조회하여 "이 키워드의 네이버 월간 검색량은 약 OO입니다"를 보여주면 어떨까요. 트렌드 시계열은 없지만 현재 검색량은 즉시 제공 가능합니다. 이러면 "데이터가 없다"가 아니라 "시계열은 준비 중이지만 현재 인기도는 이 정도입니다"가 됩니다.

---

**질문 1 잠정 합의**: 주 문구 "'{키워드}'의 트렌드 데이터를 준비 중입니다." + 유사 키워드 3개 제안(Levenshtein + 초성 매칭) + "이 키워드 알림 받기" CTA. 미등록 검색어 로깅 테이블 추가하여 주간 수요 집계. 스팸 방지: 인증 사용자 한정 + IP당 일 10건 제한. 다빈치의 즉석 네이버 검색량 표시는 Phase 2 검토 (API 호출 비용 고려).

---

### 질문 2: "Top 100에서 빠진 키워드 과거 데이터 표시" — 정확한 구현 방안

---

#### 헤르메스 (백엔드/인프라)

Cycle 3에서 합의한 active/inactive/retired 3상태를 활용합니다. inactive 키워드(이전에 Top 100이었지만 현재는 아닌)의 과거 데이터를 조회하는 API: `/api/keyword-trend/history/{keyword_id}`. 이 엔드포인트는 키워드 상태와 무관하게 trend_data 테이블에서 전체 시계열을 반환합니다. "빠진 시점"은 `keyword_rankings` 히스토리 테이블에서 추적합니다 — 매주 Top 100 스냅샷을 저장하여 특정 키워드가 언제 진입/이탈했는지 기록합니다.

#### 불칸 (백엔드 구현)

주간 스냅샷 테이블을 추가합니다. `keyword_rankings(id, keyword_id, rank, score, snapshot_date)`. 매주 일요일 배치로 현재 Top 100의 순위를 기록합니다. 과거 데이터 조회 시 이 테이블을 JOIN하면 "이 키워드는 3월 1주에 42위였다가 4월 2주에 Top 100에서 이탈했습니다"를 보여줄 수 있습니다. 쿼리: `SELECT kr.snapshot_date, kr.rank, td.value FROM keyword_rankings kr JOIN trend_data td ON kr.keyword_id = td.keyword_id WHERE kr.keyword_id = ?`.

#### 이리스 (프론트엔드)

UX 흐름을 구체화합니다. (1) Top 100 목록에서 키워드 클릭 → 상세 페이지. (2) 상세 페이지 하단에 "과거 순위 변동" 차트 — X축 시간, Y축 순위(역순, 1위가 위). (3) "이전에 인기 있었던 키워드" 별도 섹션 — inactive 상태 키워드를 회색 처리하여 목록 표시. (4) inactive 키워드 클릭 시에도 동일 상세 페이지로 이동, "현재 Top 100에 포함되지 않음" 배지 표시 + 과거 시계열 차트 표시. (5) "추이 알림 설정" 버튼 — 이 키워드가 다시 Top 100에 진입하면 알림.

#### 아테나 (전략/분석)

"빠진 키워드의 과거 데이터"가 설계사에게 주는 가치는 "계절성 파악"입니다. "태아보험"은 매년 특정 시기에 급등했다가 빠집니다. 과거 데이터를 보면 이 패턴을 인식하고, 해당 시기에 선제적으로 콘텐츠를 준비할 수 있습니다. 단순히 "과거에 인기였다"가 아니라 "언제 인기였고 언제 빠졌는가"의 시계열이 핵심입니다.

#### 아르고스 (테스트/검증)

과거 데이터 표시의 검증 시나리오: (1) 현재 Top 100에 있는 키워드의 과거 순위 변동이 차트에 정확히 표시되는지. (2) Top 100에서 이탈한 키워드를 검색했을 때 과거 데이터가 정상 로드되는지. (3) retired 상태(6개월 이상 비활성) 키워드도 데이터가 보존되어 있는지. (4) 순위 스냅샷이 매주 정확히 기록되는지 (배치 실패 시 누락 감지).

#### 로키 (레드팀)

keyword_rankings 스냅샷 테이블은 데이터가 선형으로 증가합니다. 100 키워드 x 52주/년 = 5,200행/년. 10년이면 52,000행. 규모 자체는 작지만, "왜 이 데이터를 영구 보존하는가?"를 물어야 합니다. 2년 전 순위가 설계사에게 유용한가? 최근 6개월 추이면 충분합니다. 6개월 이상 된 스냅샷은 월간 요약으로 압축하세요.

#### 마아트 (품질/검증)

스냅샷 데이터와 실시간 순위의 불일치 문제를 짚겠습니다. 설계사가 "3월 2주에 42위"라는 스냅샷을 보고, 실제 해당 주의 검색량을 역추적했을 때 순위와 맞지 않으면 신뢰도가 떨어집니다. 스냅샷 생성 시 score 값도 함께 저장하고, 스냅샷 생성 로직이 실시간 순위 산출 로직과 동일한 함수를 호출하도록 보장해야 합니다. 단일 소스 원칙.

#### 비너스 (UX/마케팅)

"이전에 인기 있었던 키워드" 섹션의 UX를 구체화합니다. 목록을 단순히 나열하면 관심을 끌기 어렵습니다. "최근 빠진 키워드"(지난 4주 내 이탈)만 하이라이트하고, 그 이전 이탈 키워드는 검색으로만 접근 가능하게 합니다. "최근 빠진 키워드"에는 "마지막 순위: 87위 → 이탈" 형태로 추세를 보여주면 "다시 올라올 수 있는지" 판단에 도움이 됩니다.

#### 아틀라스 (인프라/확장)

keyword_rankings 테이블에 파티셔닝을 적용합니다. snapshot_date 기준 월별 파티션. 6개월 이상 된 파티션은 cold storage(또는 압축)로 이동하는 lifecycle 정책을 설정합니다. Supabase PostgreSQL에서 pg_partman 확장으로 자동 파티셔닝이 가능합니다.

#### 다빈치 (혁신/대안)

과거 데이터를 단순히 "보여주는" 것을 넘어서, "이 키워드가 다시 뜰 확률"을 예측하면 어떨까요. 과거 진입/이탈 패턴 + 계절성 데이터를 기반으로 "이 키워드는 6월에 다시 Top 100 진입 확률 72%"를 표시합니다. 설계사에게 선제 대응 시그널을 줍니다. 이건 Phase 3의 "키워드 레이더"와 통합할 수 있습니다.

---

**질문 2 잠정 합의**: keyword_rankings 스냅샷 테이블 추가(주간 배치). inactive 키워드의 과거 시계열 + 순위 변동 차트 제공. "최근 빠진 키워드" 섹션(4주 이내 이탈만 하이라이트). 스냅샷 데이터 보존: 6개월 상세 + 이후 월간 압축(로키 의견 반영). score도 함께 저장(마아트 단일 소스 원칙). 다빈치의 "재진입 확률 예측"은 Phase 3.

---

### 질문 3: "사용자가 많이 없을 때 어떻게" — Layer 구성 비율의 최종 답

---

#### 헤르메스 (백엔드/인프라)

"사용자가 많이 없을 때"는 두 가지 의미입니다. (1) InsuWiki 전체 사용자가 적은 초기 단계 — Layer 3 데이터 자체가 부족. (2) 특정 주에 검색 사용자가 적어서 Layer 3 임계값(30건) 미달. 케이스 (1)은 Phase 1~2 전체 기간이므로, Layer 1 + Layer 2만으로 운영하는 것이 기본입니다. 케이스 (2)는 Phase 3 이후인데, Cycle 4에서 합의한 대로 고정 배분에서 Layer 3 슬롯을 Layer 2로 환원합니다.

#### 불칸 (백엔드 구현)

구체적인 Phase별 배분 최종안: Phase 1(사용자 <100명): L1 30개 고정 + L2 70개(네이버 검색량 순) = 100. Phase 2(사용자 100~500명): L1 30 + L2 60 + L3 10 (테스트). Phase 3(사용자 >500명): L1 30 + L2 50 + L3 20. Layer 3 임계값 미달 시: L1 30 + L2 70으로 자동 전환. 이 전환 로직은 config 테이블의 `min_l3_users` 값으로 제어합니다.

#### 이리스 (프론트엔드)

사용자가 적을 때의 UI 대응입니다. Layer 3이 비활성이면 "설계사들의 실시간 검색 트렌드" 섹션을 숨기는 것이 아니라, "곧 제공 예정 — 더 많은 설계사가 InsuWiki를 사용하면 실시간 트렌드를 확인할 수 있습니다"라는 티저를 보여줍니다. 이것은 네트워크 효과를 유도하는 UX 패턴입니다. "더 많은 동료가 참여할수록 더 좋은 데이터"라는 메시지.

#### 아테나 (전략/분석)

Phase 1에서 사용자가 적을 때의 핵심 전략은 "외부 데이터로 가치를 먼저 증명하는 것"입니다. Layer 1(전문가 큐레이션) + Layer 2(네이버 검색량)만으로도 설계사에게 충분한 가치를 제공할 수 있습니다. "보험 키워드 트렌드"라는 기능의 핵심 가치는 "어떤 키워드가 뜨고 있는지 한눈에 보는 것"이고, 이것은 네이버 데이터만으로 가능합니다. Layer 3은 부가 가치입니다.

#### 아르고스 (테스트/검증)

사용자가 적을 때의 엣지 케이스: (1) unique_users 0명 — Layer 3 완전 비활성. Top 100은 L1+L2로만 구성. (2) unique_users 1~29명 — Layer 3 비활성이지만 데이터는 수집 중. 30명 도달 시 자동 활성화. (3) unique_users가 30~35 사이에서 왔다갔다 — Cycle 4에서 논의한 히스테리시스 필요(활성화 30, 비활성화 20). (4) 특정 키워드만 unique_users가 높고 나머지가 0 — 키워드별로 활성화하면 복잡도가 폭증하므로, Layer 3 전체를 하나의 단위로 활성/비활성합니다.

#### 로키 (레드팀)

"사용자가 많이 없을 때"에 대한 최종 답은 간단합니다: "아무것도 안 합니다." Layer 3을 비활성화하고 Layer 1+2로 운영하면 됩니다. 이것은 이미 Cycle 3에서 합의된 내용입니다. 이 질문이 다시 나온 것은 "합의했지만 불안하다"는 심리인데, 불안함을 해소하는 방법은 추가 설계가 아니라 실제로 운영해보는 것입니다.

#### 마아트 (품질/검증)

최종적으로 확인해야 할 것은, Layer 3 비활성 상태에서 Top 100의 품질이 충분한가입니다. Layer 1(30개 고정) + Layer 2(70개 네이버 순위)로 구성된 Top 100을 보험업계 전문가(제이회장님 또는 실제 설계사 3명)에게 보여주고 "이 목록이 현재 보험 시장을 대표하는가?"를 검증받는 것이 Phase 1 출시 전 필수 게이트입니다.

#### 비너스 (UX/마케팅)

이리스의 "곧 제공 예정" 티저에 덧붙여, 초기 사용자에게 "키워드 투표" 기능을 제공하면 어떨까요. "다음 달에 주목할 키워드에 투표하세요" — 이것은 게이미피케이션이자 데이터 수집입니다. Layer 3이 활성화되기 전까지 사용자 참여를 유도하면서, 동시에 사용자 관심 데이터를 모을 수 있습니다. 다만 Phase 1 범위를 넘으므로 Phase 2 아이디어로 보존합니다.

#### 아틀라스 (인프라/확장)

사용자 수 증가에 따른 인프라 대응: user_search_log 테이블은 사용자가 늘면 선형으로 증가합니다. 500명이 하루 10건씩 검색하면 일 5,000건, 월 15만건. 1년이면 180만건. Supabase 무료 티어의 500MB 한도에서는 2~3년이면 압박입니다. 90일 이상 된 로그는 집계 테이블로 요약하고 원본을 삭제하는 lifecycle이 필요합니다. Phase 1에서부터 이 정책을 설계해두어야 합니다.

#### 다빈치 (혁신/대안)

사용자가 적을 때 오히려 장점이 있습니다. 소수의 초기 사용자가 검색하는 키워드는 "고관여 사용자의 실제 니즈"를 반영합니다. 대중적 키워드보다 전문적인 키워드가 나올 가능성이 높습니다. 이 데이터를 "전문가 추천 키워드"로 브랜딩하면, 사용자 수가 적다는 약점을 "전문성"이라는 강점으로 전환할 수 있습니다.

---

**질문 3 최종 답**: Phase 1은 L1(30) + L2(70) = 100. Layer 3은 Phase 3에서 unique_users 30건 이상 시 활성화. 비활성 시 Layer 2에 슬롯 환원. 초기 사용자 적을 때는 (1) 외부 데이터(네이버)로 가치 증명, (2) "곧 제공 예정" 티저로 네트워크 효과 유도, (3) 출시 전 전문가 검증 필수(마아트 게이트). user_search_log 90일 lifecycle 정책 Phase 1부터 설계(아틀라스).

---

### 질문 4: "설계사들이 검색하는 키워드 Top 100" — Phase 3의 구체적 트리거 조건

---

#### 헤르메스 (백엔드/인프라)

Phase 3 트리거 조건을 기술적 관점에서 정의합니다. (1) InsuWiki 주간 활성 사용자(WAU) 200명 이상 — 통계적으로 유의미한 샘플 크기. (2) user_search_log에 주간 unique 검색 키워드 100종 이상 — Top 100을 채울 수 있는 다양성. (3) Phase 2 안정 운영 4주 이상 — 기반 인프라 검증 완료. 세 조건 모두 충족 시 Phase 3 착수. 모니터링은 주간 배치 스크립트로 자동 체크하고, 조건 충족 시 Telegram 알림.

#### 불칸 (백엔드 구현)

Phase 3의 핵심 구현은 InsuroLogCollector입니다. BaseCollector 인터페이스를 상속하여, user_search_log 테이블에서 주간 검색 데이터를 집계합니다. `collect()` 메서드는: (1) 최근 7일간 user_search_log에서 keyword별 unique_users 카운트. (2) SHA-256 해시된 user_id 기준 중복 제거. (3) unique_users >= 3인 키워드만 필터링(최소 3명이 검색해야 유의미). (4) 보험 도메인 사전과 매칭하여 비보험 키워드 제외. (5) score 계산 후 상위 20개 반환(Layer 3 슬롯).

#### 이리스 (프론트엔드)

Phase 3 활성화 시 UI 변경: "인기 키워드 Top 100" 아래에 "설계사 실시간 검색 트렌드" 서브섹션이 추가됩니다. Layer 3 키워드에는 특별 태그("설계사들이 찾고 있는")를 붙여서 Layer 1/2와 시각적으로 구분합니다. 이 섹션은 Phase 3 트리거 조건이 충족될 때 자동으로 노출되고, 미충족 시 티저 상태를 유지합니다. 프론트엔드는 API 응답의 `layer3_active: boolean` 필드로 분기합니다.

#### 아테나 (전략/분석)

Phase 3 트리거 조건에 "비즈니스 조건"도 추가해야 합니다. 기술 조건(WAU, 검색 다양성) 외에: (1) 키워드 트렌드 기능의 주간 사용률이 DAU의 30% 이상 — 기능 자체에 관심이 있어야 Layer 3에 투자할 가치가 있음. (2) 제이회장님의 명시적 승인 — 사용자 검색 데이터 수집은 프라이버시 이슈가 있으므로 비즈니스 판단 필요.

#### 아르고스 (테스트/검증)

Phase 3 전환 시 검증 체크리스트: (1) Layer 3 키워드가 보험 도메인 사전과 100% 매칭되는지 — 비보험 키워드 유출 방지. (2) SHA-256 해시가 원본 user_id로 역추적 불가능한지 — 프라이버시 검증. (3) unique_users 카운트가 정확한지 — 같은 사용자가 다른 세션에서 검색해도 1로 카운트되는지. (4) Layer 3 활성화 전후 Top 100 목록의 변동이 예상 범위(20개 이내)인지.

#### 로키 (레드팀)

Phase 3의 가장 큰 리스크는 프라이버시입니다. "설계사들이 뭘 검색하는지"를 수집하는 것은 민감합니다. SHA-256 해시를 한다고 해도, 검색 키워드 + 검색 시간 + 접속 IP를 조합하면 개인 식별이 가능할 수 있습니다. 개인정보보호법 관점에서 (1) 검색 로그 수집에 대한 사용자 동의가 필요한지 법률 검토, (2) 검색 로그에서 IP 주소를 수집하지 않도록 명시적 제외, (3) 집계 데이터만 저장하고 원본 로그는 7일 후 삭제 — 이 세 가지가 Phase 3 착수 전 필수 조건입니다.

#### 마아트 (품질/검증)

Phase 3 데이터 품질의 핵심 지표: Layer 3에서 추출된 키워드의 "보험 적합도". 100개 중 비보험 키워드가 5개 이상이면 필터링 로직에 결함이 있는 것입니다. 주간 QC로 Layer 3 키워드 전수를 검토하고, 비적합 키워드 비율이 5% 미만을 유지하는지 모니터링합니다. 5% 초과 시 Layer 3 일시 비활성화 + 필터링 로직 수정 후 재활성화.

#### 비너스 (UX/마케팅)

Phase 3의 UX 핵심은 "내 동료들이 뭘 검색하는지"라는 사회적 증거(Social Proof)입니다. "3명의 설계사가 이번 주에 '변액보험 수익률'을 검색했습니다" — 이런 정보가 설계사에게 "나도 이걸 알아야 하나?"라는 행동 유도를 합니다. 다만 구체적 사용자 수를 표시하면 프라이버시 우려가 있으므로, "많은 설계사가 관심을 보이고 있습니다" 같은 정성적 표현으로 대체합니다.

#### 아틀라스 (인프라/확장)

Phase 3의 인프라 요구사항: user_search_log 테이블의 쓰기 성능이 중요합니다. 검색할 때마다 로그를 동기적으로 INSERT하면 검색 응답 시간이 늘어납니다. 비동기 큐(Supabase Edge Function + PostgreSQL pgmq 또는 단순 batch insert)로 처리해야 합니다. 검색 API 응답에는 영향을 주지 않고 백그라운드에서 로그를 적재합니다.

#### 다빈치 (혁신/대안)

Phase 3을 기다리지 않고 "가짜 Layer 3"을 먼저 운영하는 방법이 있습니다. InsuWiki의 기존 페이지 뷰 데이터(이미 수집 중일 가능성 높음)에서 "어떤 보험 문서를 많이 읽는지"를 추출하면, 검색 로그가 없어도 "설계사 관심 키워드"를 유추할 수 있습니다. 검색과 조회는 다르지만, "실비보험" 문서를 많이 읽으면 "실비보험"에 관심이 있는 것은 맞으니까요. 이것은 Phase 2에서 바로 도입 가능합니다.

---

**질문 4 최종 답**: Phase 3 트리거 조건 5가지. 기술 조건: (1) WAU >= 200명, (2) 주간 unique 검색 키워드 >= 100종, (3) Phase 2 안정 운영 4주 이상. 비즈니스 조건: (4) 키워드 트렌드 기능 사용률 >= DAU 30%, (5) 프라이버시 법률 검토 완료 + 사용자 동의 UI 적용. 로키 프라이버시 3대 조건(법률 검토, IP 제외, 원본 7일 삭제) 필수. 다빈치의 "페이지뷰 기반 유사 Layer 3"은 Phase 2 검토 후보.

---

## Cycle 4~5 종합 합의

### 최종 결정 사항

| 항목 | 결정 | Phase |
|---|---|---|
| Layer 2 소스 | 네이버 API(2A) 단독. Search Console은 Phase 2 Discovery Layer로 검토 | Phase 1 |
| 보험 사전 | LLM+InsuWiki+네이버 연관으로 후보 생성 → 자동 검증 → 150개로 시작 → 점진 확장 | Phase 1 |
| 슬롯 배분 | 고정 L1:30 + L2:70. 동적 배분은 Phase 3 | Phase 1 |
| 스코어링 | 이원 체계: 인기 순위(네이버 검색량) + 급상승 태그(구글 트렌드 변동률) | Phase 1 |
| 미등록 키워드 안내 | "준비 중" 문구 + 유사 3개 추천 + 알림 등록 CTA | Phase 1 |
| 과거 데이터 | keyword_rankings 스냅샷 + inactive 키워드 시계열 보존 | Phase 1~2 |
| 사용자 적을 때 | L1+L2만으로 운영. 전문가 검증 필수 | Phase 1 |
| Phase 3 트리거 | WAU>=200, unique키워드>=100, Phase2 4주, 사용률>=30%, 프라이버시 완료 | Phase 3 |

### 미해결 이슈 (다음 Cycle에서 논의)

1. BaseCollector 인터페이스의 반환 타입 상세 스키마 — Search Console 데이터를 수용할 optional 필드 설계
2. 이원 체계에서 "급상승" 판정 기준 — 주간 변동률 몇 % 이상이면 급상승인가?
3. 동의어/약어 매핑 테이블 스키마 — keyword_synonyms 테이블 설계
4. user_search_log의 90일 lifecycle 구현 방법 — pg_cron + DELETE vs 파티셔닝
5. "키워드 레이더"(다빈치) 예측 모델의 입력 데이터 요구사항 — 과거 몇 년 데이터 필요?
6. 다빈치의 "페이지뷰 기반 유사 Layer 3" 가능성 검토 — InsuWiki 기존 analytics 데이터 확인 필요
