# task-1935: 네이버 블로그 글 생성 버그 2건 수정 보고서

## SCQA

**S**: InsurWiki 대시보드의 네이버 블로그 글 생성 기능(http://localhost:8000)이 키워드 분석 → AI 글 생성 → 경쟁 분석 3단계 워크플로우를 제공 중이다. task-1934 E2E 테스트에서 2건의 버그가 발견되었다.

**C**: (1) haiku 모델로 글 생성 시 실제 블로그 글(1000자+) 대신 "WebSearch 권한 요청" 안내 메시지(529자)가 반환되어 품질 기준 미달. (2) 키워드 추천 시 보험 무관 키워드(전자소송, 법원경매, 사직서양식 등)가 추천되어 도메인 정확도 저하.

**Q**: 프롬프트 수정과 키워드 필터링 로직 추가로 2건의 버그를 해결할 수 있는가?

**A**: 3개 파일 수정으로 2건 모두 해결. (1) 프롬프트에서 웹 검색 불필요 지시 추가 + 응답 검증/재시도 로직 삽입 → 글 생성 결과 529자 → 5,093자로 정상화, WebSearch 메시지 제거. (2) 보험 도메인 키워드 44개 + 블랙리스트 21개 필터 적용 → 추천 키워드 5개 모두 보험 관련(실비보험, 실손보험, 4세대실손보험 등)으로 정상화.

---

## 수정 상세

### 버그 1: Claude CLI haiku WebSearch 권한 요청 문제

**근본 원인**: `blog_engine.py`의 `_build_naver_blog_prompt`에서 "검증 가능한 출처" 지시가 있어 haiku 모델이 웹 검색 권한을 요청하는 응답을 반환.

**수정 내용**:
1. `blog_engine.py` 프롬프트에 "웹 검색 없이 작성" 지시 추가, "검증 가능한 출처" → "공식적으로 알려진 출처"로 완화
2. `blog_writer.py`에 WebSearch 응답 감지 로직 추가: 콘텐츠 800자 미만 또는 WebSearch 키워드 포함 시 자동 재시도, 재시도 실패 시 에러 처리

### 버그 2: 키워드 추천 보험 무관 키워드 노출

**근본 원인**: `server_utils.py`의 `_naver_blog_recommended`가 검색량/경쟁도만 기준으로 정렬, 도메인 관련성 필터 없음.

**수정 내용**:
1. `_INSURANCE_DOMAIN_KEYWORDS` (44개), `_INSURANCE_BLACKLIST_KEYWORDS` (21개) 상수 추가
2. `_is_insurance_related()` 함수: 블랙리스트 → 제외, 도메인 키워드 포함 → 포함, 그 외 → 제외
3. 보험 관련 키워드 2개 이상 시 필터 적용, 미달 시 원래 결과 fallback

---

## 수정 파일별 검증 상태

| 파일 | 변경 내용 | grep 검증 | 상태 |
|------|-----------|-----------|------|
| `/home/jay/workspace/dashboard/blog_engine.py:133` | 웹 검색 불필요 지시 추가 | grep "웹 검색 없이 작성" OK | verified |
| `/home/jay/workspace/dashboard/blog_engine.py:134` | "공식적으로 알려진 출처"로 변경 | grep "공식적으로 알려진 출처" OK | verified |
| `/home/jay/workspace/dashboard/blog_engine.py:165` | GEO 출처 규칙 완화 | grep "일반적으로 알려진 정보만 서술" OK | verified |
| `/home/jay/workspace/dashboard/blog_writer.py:103-120` | WebSearch 응답 감지 + 재시도 | grep "WebSearch" OK | verified |
| `/home/jay/workspace/dashboard/server_utils.py:231-255` | 보험 도메인 키워드 필터 추가 | grep "_is_insurance_related" OK | verified |
| `/home/jay/workspace/dashboard/server_utils.py:274` | 추천 함수에 필터 적용 | grep "insurance_filtered" OK | verified |

---

## 발견 이슈 및 해결

### 이슈 1: 연산자 우선순위 버그 (해결)
- **발견**: `blog_writer.py` 라인 104에서 `or ... and ...` 조합의 연산자 우선순위 오류 발견
- **원인**: `"권한" in generated_content and "도구" in generated_content` 부분이 괄호 없이 `or`와 혼합
- **해결**: 괄호 추가하여 의도된 논리 연산 보장

### 이슈 2: 프롬프트 "수치 없이 서술" 지시 추가 필요 (해결)
- **발견**: 기존 프롬프트가 "출처 없는 수치는 절대 작성하지 말 것"으로 너무 엄격
- **해결**: "정확한 수치를 모르면 수치를 사용하지 말고 정성적으로 서술할 것"으로 완화

### 이슈 3: Pyright import 경고 (기존 — 범위 외)
- blog_engine.py, blog_writer.py의 `dashboard.server_utils` import 경고는 dashboard 모듈 구조의 기존 문제 (try/except fallback 패턴 사용 중)

---

## L1 스모크테스트 결과

- 서버 재시작: 성공 (port 8000 정상 바인딩)
- API 응답 확인:
  - POST /api/naver-blog/keyword-analysis → HTTP 200, 849개 키워드, 추천 5개 모두 보험 관련
  - POST /api/naver-blog/generate → HTTP 200, status=started
  - GET /api/naver-blog/write/status → completed, 5,093자 생성 (WebSearch 미포함)
  - POST /api/naver-blog/generate (빈 키워드) → HTTP 400
- 스크린샷: 해당없음 (API 기반 테스트)

---

## 검증 시나리오 결과

1. haiku 모델로 글 생성 → 실제 블로그 글 5,093자 반환 (WebSearch 요청 아님) **PASS**
2. 키워드 추천 → 보험 무관 키워드 제외, 보험 관련 5개만 추천 **PASS**
3. 기존 글 생성 기능 회귀 없음 → 에러 핸들링(잘못된 모델, 빈 키워드) 정상 **PASS**

---

## 모델 사용 기록

- 카르티케야(백엔드): Sonnet x2 — MT-1/MT-2 프롬프트+응답 검증 수정, MT-3 키워드 필터 추가
- 비슈누(팀장): Opus — 설계, 코드 리뷰, 연산자 우선순위 수정, L1 스모크테스트, 보고서

## 머지 판단

- **머지 필요**: No (dashboard 코드는 main 브랜치에 직접 커밋됨, insuwiki worktree에는 변경 없음)
- **브랜치**: main (dashboard repo)
- **커밋**:
  - `bd37d6d7` — Claude CLI WebSearch 권한 요청 버그 수정 (blog_engine.py, blog_writer.py)
  - `32e88cd2` — 키워드 추천에 보험 도메인 필터 추가 (server_utils.py)
  - `9a275eef` — blog_writer.py 연산자 우선순위 수정

---

## QC 자동 검증

- 결과: **PASS** (8 PASS, 7 SKIP, 3 WARN, 0 FAIL)
- full_suite_check: 2337 passed (전체 회귀 없음)
- pyright_check: 0 errors
- tdd_check: WARN (구현 먼저 → 테스트 — 버그 수정 작업이므로 정당)
- style_check: WARN (black/isort 서식 — dashboard 기존 패턴)
- .done 파일 자동 생성 완료


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


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


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

