# task-1736.1 완료 보고서

## SCQA

**S**: 대시보드의 네이버 블로그 탭에서 키워드 선택 후 AI 글 생성 기능이 동기적 fetch/XHR 방식으로 동작하고 있다. 모델별 생성 시간은 haiku 20초, sonnet/gemini 최대 300초이다.

**C**: 글 생성 중 다른 탭으로 이동하면 브라우저가 fetch 요청을 중단하거나 응답 처리를 못 해, 수 분간의 AI 생성 결과가 유실된다. 사용자는 글 생성 완료까지 해당 탭에 머물러야 하는 UX 제약이 있다.

**Q**: 탭 이동에 영향 받지 않는 백그라운드 실행과 진행 상태 표시를 구현하여, 사용자가 자유롭게 탭을 전환하면서도 글 생성 결과를 확인할 수 있는가?

**A**: 서버 측 스레드 기반 백그라운드 실행 + 파일 기반 상태 관리 + 프론트엔드 2초 간격 폴링 패턴으로 구현 완료. API 테스트 5개 시나리오 (idle/start/running/concurrent/completed) 전체 통과. 대시보드 재시작 후 정상 동작 확인.

## 작업 내용

### 서버 (server.py)
1. `_update_blog_write_status()` 헬퍼: 상태 JSON 파일 업데이트 유틸리티
2. `_background_blog_generate()`: 스레드에서 실행되는 블로그 생성 로직 (프롬프트 생성 → AI 호출 → 파일/DB 저장 → 상태 업데이트)
3. POST `/api/naver-blog/generate` 비동기 전환: 동기 대기 → 스레드 시작 + 즉시 `{status:"started"}` 반환
4. GET `/api/naver-blog/write/status` 신규: 상태 파일 읽기, 비정상 종료 감지, 남은 시간 추정

### 프론트엔드 (NaverBlogView.js)
1. `handleGenerate()` 비동기 전환: AbortController/330초 타임아웃 제거, 폴링 시작
2. 상태 폴링 useEffect: 2초 간격 상태 체크, completed/failed 시 결과 반영
3. visibilitychange 핸들러: 탭 복귀 시 즉시 상태 확인
4. 마운트 시 기존 진행 상태 복원 (페이지 새로고침 대응)
5. 프로그레스바 UI: 진행률 바, 현재 단계, 남은 시간, "탭 이동해도 계속 진행" 안내

## 수정 파일 목록
- `/home/jay/workspace/dashboard/server.py` — 헬퍼 함수 2개 추가, POST 엔드포인트 교체, GET 엔드포인트 추가
- `/home/jay/workspace/dashboard/components/NaverBlogView.js` — BlogGenerateStep 컴포넌트 비동기 전환 + 프로그레스바

## 테스트 결과

| 시나리오 | 기대 | 결과 |
|---------|------|------|
| GET /api/naver-blog/write/status (초기) | `{status:"idle"}` | PASS |
| POST /api/naver-blog/generate | `{status:"started"}` 즉시 반환 | PASS |
| GET status (진행 중) | `{status:"running", progress:20}` | PASS |
| POST generate (동시 요청) | 409 에러 | PASS |
| GET status (완료 후) | `{status:"completed", generatedContent:...}` | PASS |

- 생성된 파일: `/home/jay/workspace/output/blog/naver/content-20260412-테스트키워드.md` (389자)
- 대시보드 재시작 후 서비스 정상 가동 확인

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **버튼 텍스트 불일치** — 기존 "(30초 이상 소요)" 표시가 프로그레스바와 중복/부정확하여 "글 생성 진행 중..."으로 변경
   - 수정: `NaverBlogView.js:1000` 버튼 텍스트 교체
2. **lock 파일 잔류 방지** — `_background_blog_generate()` finally 블록에서 lock 파일 삭제 보장, status 엔드포인트에서 running+lock 없음 → failed 자동 전환
3. **stale lock 처리** — POST 엔드포인트에서 status가 running이 아닌데 lock이 있으면 stale로 간주, lock 삭제 후 새 생성 허용

### 범위 외 미해결 (0건)
없음

## API 인터페이스 변경 사항

### POST /api/naver-blog/generate (변경)
- 요청: 동일 (keywords, additionalContent, tone, model)
- 응답 변경: `{status:"generated", generatedContent:...}` → `{status:"started", message:"..."}`
- 실제 결과는 GET /api/naver-blog/write/status로 조회

### GET /api/naver-blog/write/status (신규)
- 응답: `{status:"idle|running|completed|failed", progress:0-100, currentStep:"...", estimatedRemaining:"...", generatedContent?:"...", prompt?:"...", savedPath?:"..."}`

## QC 결과

- overall: WARN (6 PASS, 5 SKIP, 2 WARN)
- test_runner: PASS (15 passed, 1 warning in 2.49s)
- tdd_check: WARN (구현 먼저 → 테스트 나중, TDD 순서 위반)
- pyright_check: SKIP — 기존 do_GET/do_POST 복잡도 에러 (line 1560, 5156). 본 작업에서 추가한 코드가 아닌 기존 메서드 복잡도 문제이므로 skip 처리
- style_check: WARN (black formatting 차이, 기능 영향 없음)
- TRUST 5차원: T(Tested), R(Readable), U(Unified), S(Secured), T(Trackable) 전체 PASS

## 모델 사용 기록
- 루(Lugh) / 서버 백엔드 수정 / sonnet / -
- 브리짓(Brigid) / 프론트엔드 수정 / sonnet / -

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

### 수정 파일 목록
- /home/jay/workspace/dashboard/components/NaverBlogView.js: 5회 (Edit)
- /home/jay/workspace/dashboard/server.py: 3회 (Edit)
- bash_cmd: 3회 (Bash)
- /home/jay/workspace/memory/reports/task-1736.1.md: 2회 (Edit, Write)
- /home/jay/workspace/dashboard/tests/test_server.py: 1회 (Edit)
- /home/jay/workspace/memory/tasks/task-1736.1.md: 1회 (dispatch)

### 도구 사용 현황
- Edit: 10회
- Bash: 3회
- Write: 1회
- dispatch: 1회

