# task-2124: 네이버 키워드 검색 완전 수정 (Lv.4 — 근본 원인 확인됨)

## ★ 프로젝트: `/home/jay/projects/InsuRo/`

## 근본 원인 (아누 직접 분석 완료)

네이버 SearchAd API `/keywordstool`의 `hintKeywords` 파라미터는 **공백(space)을 허용하지 않음**.
- `실비보험` → 200 OK (754건)
- `실비보험 가격` → 400 ERROR `{"code":11001,"message":"hintKeywords 파라미터가 유효하지 않습니다"}`
- `실비 보험` → 400 ERROR (같은 에러)
- `실비보험,가격` → 200 OK (콤마 구분은 정상)

**대시보드 working 코드** (`/home/jay/workspace/dashboard/routes_post.py:1810`):
```python
keywords = [k.strip() for k in re.split(r"[,\s]+", raw_keyword) if k.strip()]
```
→ 공백/콤마를 구분자로 분할 → 개별 키워드마다 API 호출 → 결과 병합

**InsuRo 현재 코드** (`server/main.py:835-836`):
```python
encoded_kw = urllib.parse.quote(req.query, safe="")
sa_url = f"https://api.searchad.naver.com{api_path}?hintKeywords={encoded_kw}&showDetail=1"
```
→ 사용자 입력을 그대로 URL 인코딩하여 전달 → **공백 포함 시 에러**

## 수정 사항

### 1. server/main.py — search_type=="keyword" 분기 수정

`encoded_kw = urllib.parse.quote(req.query, safe="")` 라인을 다음으로 교체:

```python
import re  # 상단에 없으면 추가

# 공백/콤마로 분할하여 개별 키워드 추출
keywords = [k.strip() for k in re.split(r"[,\s]+", req.query) if k.strip()]
if not keywords:
    raise HTTPException(status_code=400, detail="유효한 키워드를 입력하세요")

# 각 키워드별로 API 호출 후 결과 병합 (중복 제거)
all_results = []
seen = set()
for kw in keywords:
    timestamp = str(round(time.time() * 1000))
    sign_msg = f"{timestamp}.{method}.{api_path}"
    signature = base64.b64encode(
        hmac_mod.new(
            searchad_secret_key.encode("utf-8"),
            sign_msg.encode("utf-8"),
            hashlib.sha256,
        ).digest()
    ).decode("utf-8")
    encoded_kw = urllib.parse.quote(kw, safe="")
    sa_url = f"https://api.searchad.naver.com{api_path}?hintKeywords={encoded_kw}&showDetail=1"
    sa_resp = await _naver_http_client.get(
        sa_url,
        headers={
            "X-Timestamp": timestamp,
            "X-API-KEY": searchad_api_key,
            "X-Customer": searchad_customer_id,
            "X-Signature": signature,
        },
    )
    if sa_resp.status_code == 200:
        for item in sa_resp.json().get("keywordList", []):
            rel_kw = item.get("relKeyword", "")
            if rel_kw not in seen:
                seen.add(rel_kw)
                all_results.append(item)

if not all_results:
    raise HTTPException(status_code=502, detail="네이버 API에서 결과를 가져오지 못했습니다")

return {"keywordList": all_results}
```

### 2. 핵심 포인트
- `re.split(r"[,\s]+", req.query)` — 공백과 쉼표를 구분자로 키워드 분리
- 각 키워드마다 **새 timestamp + 새 signature** 생성 (시간이 다르므로)
- 결과 병합 시 `relKeyword` 기준 중복 제거
- 빈 키워드 필터링 (`if k.strip()`)

### 3. 추가 — 입력 검증 강화
`req.query.strip()` 체크도 상단에 추가:
```python
if not req.query or not req.query.strip():
    raise HTTPException(status_code=400, detail="키워드를 입력하세요")
```

## ★ 먼저 읽을 파일
- `/home/jay/projects/InsuRo/server/main.py` — L785~855 (naver_proxy 함수 전체)
- 상단 import 확인: `re`, `time`, `hashlib`, `hmac`, `base64`, `urllib.parse` 모두 있는지

## 검증 시나리오 (이게 되면 성공)

### 테스트 1: 단일 키워드 (기존 동작 유지)
```bash
curl -s -X POST http://localhost:8001/api/insuro/naver/search \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <JWT>" \
  -d '{"query":"실비보험","search_type":"keyword"}'
```
→ keywordList에 700+ 항목 반환

### 테스트 2: 공백 포함 키워드 (핵심 — 이전에 에러 발생하던 케이스)
```bash
curl -s -X POST http://localhost:8001/api/insuro/naver/search \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <JWT>" \
  -d '{"query":"실비보험 가격","search_type":"keyword"}'
```
→ "실비보험"과 "가격" 각각의 결과 병합 반환, 에러 없음

### 테스트 3: 쉼표 구분 키워드
```bash
curl -s -X POST http://localhost:8001/api/insuro/naver/search \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <JWT>" \
  -d '{"query":"실비보험,암보험,치아보험","search_type":"keyword"}'
```
→ 3개 키워드의 결과 병합 반환

### 테스트 4: 빈 문자열
```bash
curl -s -X POST http://localhost:8001/api/insuro/naver/search \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <JWT>" \
  -d '{"query":"  ","search_type":"keyword"}'
```
→ 400 에러 "유효한 키워드를 입력하세요"

### 테스트 5: JWT 없이 호출
→ 401 에러 (기존 동작 유지)

## 서비스 재시작
```bash
systemctl --user restart insuro-api
systemctl --user status insuro-api
```

## 완료 시그니처
- `{"code":11001,"message":"hintKeywords 파라미터가 유효하지 않습니다"}` 에러 완전 해소
- 단일/복합/쉼표구분 키워드 모두 정상 동작
- 기존 datalab, blog search_type 영향 없음
- insuro.biz에서 키워드 분석 탭 → 키워드 입력 → 결과 표시

## 레벨
- critical (Lv.4 — 5회 이상 실패 후 근본 원인 규명)

## 프로젝트
- insuro