# task-1697.1 완료 보고서: 블로그 이미지 템플릿 기반 아키텍처 전환 구현

## S - Situation
블로그 이미지 생성 파이프라인(image_router.py)이 Claude CLI(haiku) HTML 생성 → Playwright PNG 변환 방식으로 운영 중이다. Agent Meeting(task-1695.1)에서 전원 합의: 사전 정의 Satori 템플릿 + LLM JSON 데이터 추출 방식으로 아키텍처 전환 필요.

## C - Complication
7차례 수정(task-1616.1 ~ task-1670.1)에도 블로그 이미지 품질 문제 반복. LLM이 매번 HTML을 새로 생성하는 비결정적 파이프라인이 근본 원인. 프롬프트 텍스트가 이미지에 출력되는 핵심 버그 재발, 아이콘만 배치되는 구조적 실패 반복.

## Q - Question
Agent Meeting 합의대로 `_prompt_to_html()` → `_extract_structured_json()` + Satori 고정 템플릿 아키텍처 전환을 구현하여 결정적 품질 출력을 달성할 수 있는가?

## A - Answer
아키텍처 전환 구현 완료. (1) `_prompt_to_html()` 제거 → `_extract_structured_json()` 신규 (LLM은 JSON 데이터 추출만 수행), (2) satori_cli.js에 `--json` 모드 추가 (6유형 고정 템플릿), (3) `_render_json_to_png()` 신규 추가로 Satori 단일 렌더링 경로 확립, (4) design-tokens.json에 blog 섹션 추가. pytest 103건 전체 통과(1.08s), pyright 에러 0건.

## 구현 상세

### 1. image_router.py — 핵심 리팩터링
- `_prompt_to_html()` (구 281~355행) 완전 제거
- `_extract_structured_json(description, img_type) -> dict | None` 신규 (282~381행)
  - Claude CLI haiku로 JSON 스키마 기반 데이터 추출
  - 최대 3회 재시도 + JSON 파싱 에러 시 피드백 포함 4번째 재시도
  - HTML 생성 완전 배제 → 프롬프트 텍스트 렌더링 버그 원천 차단
- `_render_json_to_png(json_data, output_path) -> bool` 신규 (486~504행)
  - Satori `--json` 모드 subprocess 호출
- `_generate_infographic()` 수정: JSON 추출 → Satori 렌더링 파이프라인

### 2. satori_cli.js — --json 모드 추가
- CLI 파싱에 `--json` 옵션 추가
- design-tokens.json 로딩 + 디자인 토큰 변수화
- 6유형 JSON 템플릿 함수: infographic, comparison_table, checklist, process_flow, chart, generic(fallback)
- 기존 `--prompt` 모드 완전 유지 (하위 호환)

### 3. design-tokens.json — blog 섹션 추가
- typography (title 28px, subtitle 20px, body 14px)
- spacing (padding 32px, gap 16px)
- maxItems (comparison=8, checklist=10, process_flow=6, chart=8, infographic=6)
- colors (배경 그라데이션, 액센트 컬러 등)

### 4. 테스트 갱신
- `TestPromptToHtml` → `TestExtractStructuredJson` (6개 테스트)
- `TestPromptToHtmlRetry` → `TestExtractStructuredJsonRetry` (7개 테스트, JSON 파싱 에러 피드백 포함)
- `TestPromptToHtmlDesignTokens` → `TestExtractStructuredJsonSchema` (3개 테스트)
- `TestRenderJsonToPng` 신규 (5개 테스트)
- `test_infographic_fails_when_json_none` 교체 (1개)
- 기존 테스트 유지: 81개 (enum, dataclass, routing, fallback, QC 등)
- **총 103개 테스트 전체 PASSED**

## 발견 이슈 및 해결

### 자체 해결 (3건)
1. **`import json` 네임 충돌 방지** — `import json as _json`으로 명명하여 image_router.py 내부 네임스페이스 충돌 방지
2. **JSON 파싱 에러 피드백 재시도** — 3회 루프 내 파싱 에러 축적 후 4번째 시도에 에러 메시지를 프롬프트에 포함하여 LLM 자기교정 유도
3. **generic fallback 유형 구현** — 분류 불능 콘텐츠(혼합형 등) 처리를 위한 범용 카드 레이아웃 추가, JSON type 필드가 인식 불가 시 자동 라우팅

## 산출물 파일
- `/home/jay/workspace/tools/ai-image-gen/image_router.py`
- `/home/jay/workspace/tools/ai-image-gen/satori-test/satori_cli.js`
- `/home/jay/workspace/tools/ai-image-gen/design-tokens.json`
- `/home/jay/workspace/tools/ai-image-gen/test_image_router.py`
- `/home/jay/workspace/memory/reports/task-1697.1.md`

## 모델 사용 기록
- 토르(백엔드): sonnet / image_router.py 리팩터링 + design-tokens.json 블로그 섹션 / 정당성: 기본 코딩 모델
- 프레이야(프론트엔드): sonnet / satori_cli.js --json 모드 구현 / 정당성: 기본 코딩 모델
- 헤임달(테스터): sonnet / test_image_router.py 테스트 갱신 / 정당성: 기본 코딩 모델

## 셀프 QC
- [x] 1. 영향 파일: image_router.py, satori_cli.js, design-tokens.json, test_image_router.py (모두 본 작업 범위)
- [x] 2. 엣지 케이스: JSON 파싱 에러→피드백 재시도, 빈 응답→None, 분류 불능→generic fallback
- [x] 3. 작업 지시 일치: Agent Meeting 합의 8개 항목 모두 구현
- [x] 4. 에러 처리/보안: subprocess 타임아웃 120s, JSON 파싱 예외 처리, 로깅
- [x] 5. 테스트 커버리지: 103개 전체 PASSED (1.08s), 새 함수 3개 모두 커버
- [x] 6. 이슈 모두 해결: 3건 자체 해결 완료
- [x] 7. 아키텍처 원칙: Composition 패턴(템플릿 셸 + 토큰 분리), SRP 준수
- [x] 8. 인터페이스 변경: _prompt_to_html→_extract_structured_json 교체, 테스트 전면 갱신
- [x] 9. HTML/PNG 대응: N/A (이번 작업은 HTML 생성을 배제하는 변경)
- [x] 10. CLAUDE.md 100줄 미만: 팀 CLAUDE.md 미변경

## QC 자동 검증
```
pytest: 103 passed (1.08s)
pyright: 0 errors, 0 warnings
black: reformatted (수정 완료)
```

## 머지 판단
- **머지 필요**: No (worktree 미사용, 시스템 작업)

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

### 수정 파일 목록
- bash_cmd: 7회 (Bash)
- /home/jay/workspace/tools/ai-image-gen/test_image_router.py: 6회 (Edit)
- /home/jay/workspace/tools/ai-image-gen/satori-test/satori_cli.js: 4회 (Edit)
- /home/jay/workspace/tools/ai-image-gen/image_router.py: 3회 (Edit)
- /home/jay/workspace/memory/reports/task-1697.1.md: 1회 (Write)
- /home/jay/workspace/memory/tasks/task-1697.1.md: 1회 (dispatch)
- /home/jay/workspace/tools/ai-image-gen/design-tokens.json: 1회 (Edit)

### 도구 사용 현황
- Edit: 14회
- Bash: 7회
- Write: 1회
- dispatch: 1회

