IMPROVEMENT Phase A~D + Phase 2 전체 반영
## IMPROVEMENT (Phase A~D) - A-1: 4단계 Sonnet 디자인 조정 (_adjust_design) — CSS 변수 cascade - A-2: 5단계 HTML 전문 프롬프트 전달 - A-3: shrink/expand 하드코딩 제거 → Sonnet target_ratio 기반 - A-4: rewrite action 구현 - A-5: overflow: visible (area 레벨 텍스트 잘림 방지) - A-6: object-fit cover → contain (이미지 crop 방지) - A-7: table-layout: fixed - A-8: container query 폰트 스케일링 - B-1: details-block 템플릿 신규 (CSS 변수만 사용) - B-2: 인쇄 시 details 자동 펼침 JS - B-3: catalog에 details-block 등록 - B-4/B-5: images[]/tables[] 상세 판단 + fallback 3곳 동기화 - B-8: fallback card-grid → topic-header + char_guide 제거 - C-1: CLAUDE.md gradient 원칙 완화 - C-3: border-radius 9개 파일 var(--radius) 통일 - C-4: box-shadow 2레벨 → 1레벨 - D-0: 이미지 경로 입력 UI + API base_path - D-1: Pillow 의존성 + image_utils.py - D-2~D-4: 이미지 비율/축소방지 프롬프트 전달 - D-5: HTML에 이미지 base64 삽입 ## Phase 2 (다른 Claude 작업) - P2-A: FAISS 블록 검색 (bge-m3, 46개 블록) - P2-B: SVG N개 자동 배치 (svg_calculator.py) - P2-C: Opus 블록 추천 (Kei API 경유) - P2-D: 5단계 재검토 루프 강화 (MAX_REVIEW_ROUNDS=2) - P2-E: details-block fallback 연동 ## 버그 수정 (BF-8~10) - BF-8: 컨테이너 예산 기반 블록 배치 - BF-9: grid와 Sonnet 역할 분리 - BF-10: catalog mtime 캐시 자동 갱신 ## 블록 라이브러리 - 46개 블록 (6 카테고리), catalog/BLOCK_SLOTS/INDEX 동기화 - 구 블록 제거 (quote-block, card-grid, comparison) - 13개 _legacy 블록 보존 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
190
PLAN.md
190
PLAN.md
@@ -170,25 +170,191 @@
|
||||
- **의존성:** 없음
|
||||
- **완료 기준:** 다운로드한 HTML 파일에서 한글 정상 표시
|
||||
|
||||
### BF-4: body 블록 겹침 (같은 area에 여러 div)
|
||||
- **파일:** src/renderer.py
|
||||
- **내용:** 같은 area의 블록을 하나의 div로 그룹핑 (OrderedDict + flex-column)
|
||||
- **기술:** Python OrderedDict (내장)
|
||||
- **의존성:** BF-5 (area명 통일 선행)
|
||||
- **완료 기준:** body에 4개 블록이 세로로 쌓여서 보임 (겹침 없음)
|
||||
- **상태:** 코드 수정 완료, md 반영 중
|
||||
|
||||
### BF-5: 제목 안 보임 (area명 불일치)
|
||||
- **파일:** src/design_director.py (LAYOUT_PRESETS)
|
||||
- **내용:** 프리셋 4개의 area명 `title` → `header`로 통일 (slide-base.html이 `header` 사용)
|
||||
- **기술:** 문자열 교체
|
||||
- **의존성:** 없음
|
||||
- **완료 기준:** 슬라이드에 제목이 표시됨
|
||||
- **상태:** sidebar-right 프리셋 수정 완료, 나머지 3개 확인 필요
|
||||
|
||||
### BF-6: sidebar 카드 3열 찢어짐
|
||||
- **파일:** src/design_director.py (STEP_B_PROMPT)
|
||||
- **내용:** 팀장 Step B 프롬프트에 "sidebar zone은 전체 너비의 35%로 좁다. card-grid 배치 시 카드 열 수를 공간에 맞게 판단하라" 추가
|
||||
- **기술:** 프롬프트 엔지니어링
|
||||
- **의존성:** 없음
|
||||
- **완료 기준:** sidebar의 카드가 1열 세로로 배치됨
|
||||
- **상태:** 미수정
|
||||
|
||||
### BF-7: body 블록 텍스트 비어있음 (content_editor 매칭 오류)
|
||||
- **파일:** src/content_editor.py
|
||||
- **내용:** 같은 area에 여러 블록이 있을 때 첫 번째만 매칭되는 문제. `break` 제거 + area+topic_id로 정확 매칭. 편집자 프롬프트 출력 형식에 `topic_id` 추가.
|
||||
- **기술:** Python 조건문 수정
|
||||
- **의존성:** 없음
|
||||
- **완료 기준:** body의 모든 블록에 텍스트가 채워짐
|
||||
- **상태:** 미수정
|
||||
|
||||
### BF-8: 컨테이너 예산 기반 블록 배치 (프레임 넘침 방지)
|
||||
- **파일:** src/design_director.py, templates/catalog.yaml, static/base.css, templates/blocks/visuals/*.html
|
||||
- **내용:**
|
||||
- 근본 원인: 팀장이 콘텐츠 중심으로 블록 선택 → 높이 고려 없이 body에 4개 블록 쌓음 → 720px 초과 → overflow:hidden으로 잘림
|
||||
- 해결: 컨테이너(zone) 크기 예산을 먼저 확인하고, 예산 안에서 블록을 선택하는 사고 순서로 전환
|
||||
- LAYOUT_PRESETS: zone별 budget_px + width_pct 추가
|
||||
- STEP_B_PROMPT: 4단계 사고 순서 (컨테이너 확인→배정→블록 선택+높이 계산→검증)
|
||||
- catalog.yaml: 블록별 height_cost 추가 (compact ~70px / medium ~150px / large ~200px / xlarge ~400px)
|
||||
- base.css: area 컨테이너에 overflow:hidden + min-height:0 안전망
|
||||
- 시각화 블록 CSS: flex-shrink + responsive SVG
|
||||
- **기술:** 프롬프트 엔지니어링 + CSS 안전망
|
||||
- **의존성:** 없음
|
||||
- **완료 기준:** body 영역 블록이 720px 프레임 안에 모두 보임. 넘침 없음.
|
||||
- **한계:** 프롬프트만으로는 Sonnet이 grid를 무시하는 문제를 방지할 수 없음 → BF-9 필요
|
||||
|
||||
### BF-9: grid와 Sonnet의 역할 분리 (설계 수정)
|
||||
- **파일:** src/design_director.py
|
||||
- **내용:**
|
||||
- 설계 오류: Step B에서 Sonnet에게 grid 값을 출력하라고 요구 → Sonnet이 자기만의 grid를 생성해버림
|
||||
- 근본 원인: grid는 코드(Step A)가 결정하는 것인데 Sonnet에게 에코를 요구한 것 자체가 잘못
|
||||
- 해결:
|
||||
- Step B 프롬프트에서 grid 출력 요구 제거. Sonnet은 `blocks` 배열만 출력
|
||||
- `create_layout_concept()`에서 grid 값은 프리셋에서 직접 가져옴 (Sonnet 출력 무시)
|
||||
- Sonnet이 출력한 area명이 프리셋 zone에 없으면 가장 가까운 zone으로 코드 매핑
|
||||
- 원칙: **코드가 결정한 것은 코드가 유지한다. Sonnet은 콘텐츠 판단만.**
|
||||
- **기술:** Python 코드 수정 + 프롬프트 출력 형식 변경
|
||||
- **의존성:** BF-8 (프리셋에 zone 정보 필요)
|
||||
- **완료 기준:** Sonnet 출력에 grid 값이 없음. 최종 HTML의 grid는 항상 프리셋과 100% 일치.
|
||||
|
||||
### BF-10: _CATALOG_MAP 캐시 갱신 문제
|
||||
- **파일:** src/renderer.py
|
||||
- **내용:**
|
||||
- 현상: catalog.yaml을 수정해도 서버 재시작 전까지 구 매핑 유지 → _legacy 블록 로드
|
||||
- 근본 원인: _CATALOG_MAP이 모듈 레벨 global로 한 번만 로드됨
|
||||
- 해결: reload 옵션 (--reload 시 자동 갱신) 또는 매 요청마다 파일 mtime 확인 후 reload
|
||||
- **기술:** Python pathlib stat() (내장)
|
||||
- **의존성:** 없음
|
||||
- **완료 기준:** catalog.yaml 수정 → 서버 재시작 없이 새 매핑 적용
|
||||
|
||||
### DA-16: 통합 테스트
|
||||
- **파일:** tests/test_pipeline.py, tests/test_renderer.py
|
||||
- **내용:** 전체 파이프라인 테스트 + 블록 렌더링 테스트
|
||||
- **의존성:** BF-2, BF-3
|
||||
- **의존성:** BF-2, BF-3, BF-4, BF-5, BF-6, BF-7
|
||||
- **완료 기준:** 테스트 전체 통과
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: 블록 라이브러리 확장
|
||||
|
||||
### DA-17: Figma 에셋 추출 + 블록 템플릿 제작
|
||||
- **상태:** done
|
||||
- **산출물:**
|
||||
- Figma 스크린샷 16장 (`docs/figma-screenshots/`)
|
||||
- Figma 에셋 15개+ (`docs/figma-assets/`)
|
||||
- 신규 블록 템플릿 6종 (`templates/blocks/` 카테고리별)
|
||||
- 디자인 분석 보고서 (`docs/figma-analysis/DESIGN-ANALYSIS.md`)
|
||||
- 블록 인덱스 (`templates/blocks/INDEX.md`)
|
||||
- **완료 기준:** 신규 블록 6개 독립 렌더링 테스트 통과, Figma 톤 반영
|
||||
|
||||
### DA-18: 블록 라이브러리 카테고리 재편
|
||||
- **상태:** done
|
||||
- **내용:** 플랫 구조 → 6개 카테고리 폴더 (headers, cards, tables, visuals, emphasis, media)
|
||||
- **완료 기준:** INDEX.md에 전체 구조 정리, 기존 루트 파일 정리
|
||||
|
||||
### DA-19: 변형 확장
|
||||
- **상태:** done (46개 달성)
|
||||
- **산출물:** 46개 블록 (6 카테고리), catalog.yaml 46개, BLOCK_SLOTS 46개 동기화
|
||||
- **완료 기준:** ✅ 달성
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: 파이프라인 고도화 (상세: docs/PHASE2-PLAN.md, PHASE2-PROCESS.md)
|
||||
|
||||
### P2-A: FAISS 블록 검색 인덱스
|
||||
- **파일:** `src/block_search.py` (신규), `scripts/build_block_index.py` (신규), `src/design_director.py` (수정)
|
||||
- **내용:** catalog 전문 → FAISS 검색으로 관련 블록 5~8개만 프롬프트에 전달
|
||||
- **기술:** BAAI/bge-m3 + faiss-cpu (Kei persona와 동일 패턴)
|
||||
- **의존성:** 없음
|
||||
- **완료 기준:** 꼭지별 검색 → 카테고리별 최소 1개 보장 → 프롬프트 토큰 절약
|
||||
|
||||
### P2-B: SVG N개 자동 배치
|
||||
- **파일:** `src/svg_calculator.py` (신규), `src/renderer.py` (수정), `templates/blocks/visuals/venn-diagram.html` (수정)
|
||||
- **내용:** venn-diagram 3개 고정 → N개(2~7) cos/sin 자동 계산
|
||||
- **기술:** Python math (내장, 추가 의존성 없음)
|
||||
- **의존성:** 없음 (2-A와 병렬 가능)
|
||||
- **완료 기준:** N=2~7 각각 렌더링 테스트 통과. Phase 1 fallback 유지.
|
||||
|
||||
### P2-C: Step A Opus+FAISS 고도화
|
||||
- **파일:** `src/design_director.py` (수정)
|
||||
- **내용:** 규칙 4줄 → Opus(Kei API)가 FAISS 후보에서 블록 선정 + 배치 결정
|
||||
- **기술:** Kei API 호출 (Opus). anthropic 직접 호출 **절대 금지**.
|
||||
- **의존성:** P2-A 완료 필수
|
||||
- **완료 기준:** Opus가 콘텐츠 보고 블록 후보 선정. Kei API 실패 시 기존 방식 fallback.
|
||||
|
||||
### P2-D: 5단계 재검토 강화
|
||||
- **파일:** `src/pipeline.py` (수정)
|
||||
- **내용:** shrink/rewrite action 구현 + 재조정 루프 (MAX=2)
|
||||
- **기술:** Anthropic API (Sonnet) — 기존 패턴
|
||||
- **의존성:** 없음 (병렬 가능)
|
||||
- **완료 기준:** expand/shrink/rewrite 3개 action 모두 동작. 루프 2회 제한.
|
||||
|
||||
### P2-E: 누락 기능
|
||||
- **E-1 Pillow:** `src/design_director.py` — 이미지 크기 읽기 → 블록 선택 참고
|
||||
- **E-2 details-block:** `src/design_director.py` + `src/pipeline.py` — detail_target → details-block 배치
|
||||
- **의존성:** 없음 (병렬 가능)
|
||||
- **완료 기준:** 이미지 크기 정보가 팀장에게 전달. details 접기/펼치기 동작.
|
||||
|
||||
### 의존 관계
|
||||
```
|
||||
P2-A (FAISS) ──────────────────────┐
|
||||
├→ P2-C (Opus+FAISS)
|
||||
P2-B (SVG N개) ── 병렬 │
|
||||
P2-D (재검토) ─── 병렬 │
|
||||
P2-E (누락기능) ── 병렬 │
|
||||
```
|
||||
|
||||
### DA-21: renderer 카테고리 경로 지원
|
||||
- **상태:** todo
|
||||
- **내용:** `renderer.py`의 블록 로드 경로를 `blocks/{type}.html` → `blocks/{category}/{name}.html`로 변경
|
||||
- **주의:** 기존 파이프라인과 호환성 유지
|
||||
- **의존성:** DA-18
|
||||
- **완료 기준:** 카테고리 경로로 블록 렌더링 정상 동작
|
||||
|
||||
### DA-22: catalog.yaml 경로 업데이트
|
||||
- **상태:** todo
|
||||
- **내용:** template 경로를 새 폴더 구조로 반영
|
||||
- **의존성:** DA-21
|
||||
- **완료 기준:** catalog.yaml의 모든 template 경로가 실제 파일과 일치
|
||||
|
||||
---
|
||||
|
||||
## 의존 관계
|
||||
|
||||
```
|
||||
DA-1 → DA-2 → DA-12(실장) → DA-13a(프리셋) → DA-13b(블록배치) → DA-13c(편집자) ─┐
|
||||
├→ DA-14(조립+재검토) → DA-15 → DA-16
|
||||
DA-3 → DA-4~DA-10 → DA-11(렌더러) ──────────────────────────────────────────────┘
|
||||
Phase 1~2 (기반+블록):
|
||||
DA-1 → DA-2, DA-3 → DA-4~DA-10 → DA-11(렌더러)
|
||||
|
||||
Phase 3 (AI 파이프라인):
|
||||
DA-12(실장) → DA-13(팀장) → DA-13b(편집자) → DA-14(조립+재검토)
|
||||
|
||||
Phase 4 (UI):
|
||||
DA-14 → DA-15(프론트엔드) → DA-16(테스트)
|
||||
|
||||
Phase 5 (블록 라이브러리):
|
||||
DA-17(Figma추출) → DA-18(카테고리재편) → DA-19(변형확장) → DA-20(FAISS)
|
||||
DA-18 → DA-21(renderer경로) → DA-22(catalog경로)
|
||||
```
|
||||
|
||||
- Phase 1~2: AI 없이 진행 가능
|
||||
- Phase 1~2, 5: AI 없이 진행 가능
|
||||
- Phase 3: Anthropic API 필요 (5단계 파이프라인)
|
||||
- 5단계 흐름: 실장 → 팀장 → 편집자 → 조립 → 재검토
|
||||
- Phase 5는 Phase 3와 **병렬** 진행 가능
|
||||
|
||||
---
|
||||
|
||||
@@ -196,10 +362,12 @@ DA-3 → DA-4~DA-10 → DA-11(렌더러) ─────────────
|
||||
|
||||
| 역할 | 도구 | 비고 |
|
||||
|------|------|------|
|
||||
| 서버 | FastAPI + uvicorn | Kei와 동일 |
|
||||
| 템플릿 엔진 | Jinja2 | 블록 상속 + 슬롯 변수 |
|
||||
| 렌더링 | CSS Grid + 디자인 토큰 | 순수 CSS |
|
||||
| 서버 | FastAPI + uvicorn | 포트 8001 |
|
||||
| 템플릿 엔진 | Jinja2 | 카테고리별 블록 조합 |
|
||||
| 렌더링 | CSS Grid + 디자인 토큰 | 슬라이드 + 웹 |
|
||||
| 한국어 폰트 | Pretendard Variable | word-break: keep-all |
|
||||
| AI (실장) | Kei API (Opus) | localhost:8000 |
|
||||
| AI (팀장) | Anthropic API (Sonnet) | Structured Outputs |
|
||||
| AI (5단계) | Anthropic API (Sonnet) | 실장→팀장→편집자→실무자→재검토 |
|
||||
| 이미지 생성 | Gemini API | 복합 시각화 배경 (레이어 방식) |
|
||||
| Figma | Figma REST API + Framelink MCP | 에셋 추출 |
|
||||
| 변형 검색 | FAISS (향후) | 블록 40개+ 시 |
|
||||
| 테스트 | pytest | 렌더링 + 파이프라인 |
|
||||
|
||||
Reference in New Issue
Block a user