04. design_agent 추가 — 콘텐츠 시각 구조화 슬라이드 생성기
5단계 AI 파이프라인: 1. Kei 실장(Opus via Kei API) — 꼭지 추출 + 정보 구조 파악 2. 디자인 팀장 — FAISS 블록 검색 + Opus 추천 + Sonnet 블록 매핑 3. Kei 편집자(Kei API) — 도메인 전문 텍스트 정리 4. 디자인 실무자(Sonnet + Jinja2) — CSS 변수 조정 + HTML 조립 5. 디자인 팀장(Sonnet) — 균형 재검토 (최대 2회 루프) 블록 라이브러리 46개 (6 카테고리) + _legacy 13개 FAISS 블록 검색 (bge-m3, 1024차원) SVG N개 동적 배치 (cos/sin 좌표 계산) Pillow 이미지 크기 측정 + base64 인라인 컨테이너 예산 기반 블록 배치 (zone별 높이 px) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
309
04. design_agent/IMPROVEMENT.md
Normal file
309
04. design_agent/IMPROVEMENT.md
Normal file
@@ -0,0 +1,309 @@
|
||||
# Design Agent — 개선 계획
|
||||
|
||||
CLAUDE.md 요구사항 전수검토 결과 발견된 미구현/부분구현/위반 사항 33개의 개선 계획.
|
||||
2026-03-25 기준 코드 감사 결과에 기반.
|
||||
|
||||
---
|
||||
|
||||
## Phase A: 슬라이드 품질 핵심 (8개)
|
||||
|
||||
> "프레임에 내용이 안 보인다"의 직접 원인. 최우선.
|
||||
> **실행 상세:** [IMPROVEMENT-PHASE-A.md](IMPROVEMENT-PHASE-A.md)
|
||||
|
||||
### A-1: 4단계 Sonnet 디자인 조정 추가
|
||||
- **현재:** Jinja2 렌더링만 수행. 텍스트 길이에 맞는 디자인 조정 없음.
|
||||
- **CLAUDE.md:** "디자인 실무자 (Sonnet + Jinja2 + CSS) — 편집자가 정리한 텍스트에 맞게 폰트/여백/박스 조정"
|
||||
- **작업:** pipeline.py 4단계에서 render_slide() 호출 전, Sonnet이 블록별 텍스트 길이를 보고 CSS 조정값(font-size, padding, gap 등)을 결정하는 호출 추가
|
||||
- **파일:** pipeline.py, 새 함수 또는 renderer.py 확장
|
||||
- **의존성:** 없음
|
||||
|
||||
### A-2: 5단계 HTML을 프롬프트에 전달
|
||||
- **현재:** `_review_balance(html, ...)` 시그니처에 html 있지만 프롬프트에 미포함. 데이터 길이만 전달.
|
||||
- **CLAUDE.md:** "1차 조립 결과의 전체 균형 확인"
|
||||
- **작업:** _review_balance() 프롬프트에 HTML 구조 요약 또는 전문 포함
|
||||
- **파일:** pipeline.py `_review_balance()`
|
||||
- **의존성:** 없음
|
||||
|
||||
### A-3: 5단계 shrink action 구현
|
||||
- **현재:** `_apply_adjustments()`에서 `action in ("expand", "rewrite")` 조건만 처리. shrink 무시.
|
||||
- **작업:** shrink 시 char_guide 값을 0.7배로 축소하는 분기 추가
|
||||
- **파일:** pipeline.py `_apply_adjustments()`
|
||||
- **의존성:** 없음
|
||||
|
||||
### A-4: 5단계 rewrite action 구현
|
||||
- **현재:** rewrite가 expand와 같은 조건에 들어가지만 실제 동작 없음 (no-op).
|
||||
- **작업:** rewrite 시 해당 블록의 data를 초기화하고 fill_content()로 재편집
|
||||
- **파일:** pipeline.py `_apply_adjustments()`
|
||||
- **의존성:** 없음
|
||||
|
||||
### A-5: overflow:hidden vs "텍스트 자르지 않는다" 원칙 해소
|
||||
- **현재:** base.css에 `.slide { overflow: hidden }` + `.slide > div { overflow: hidden }`. 텍스트 넘치면 잘림.
|
||||
- **CLAUDE.md:** "텍스트를 자르지 않는다 (디자인이 텍스트에 맞춘다)"
|
||||
- **작업:** A-1(Sonnet 디자인 조정)으로 넘침을 사전 방지. `.slide > div`의 overflow를 재검토. 최소한 텍스트 블록은 overflow: visible 또는 auto 허용.
|
||||
- **파일:** static/base.css
|
||||
- **의존성:** A-1 완료 후 정책 결정
|
||||
|
||||
### A-6: object-fit: cover → contain 수정
|
||||
- **현재:** image-row-2col.html, image-grid-2x2.html에서 `object-fit: cover` 사용 → 이미지 crop 발생
|
||||
- **CLAUDE.md:** "이미지를 crop하지 않는다", "object-fit: contain"
|
||||
- **작업:** cover → contain으로 변경
|
||||
- **파일:** templates/blocks/media/image-row-2col.html, templates/blocks/media/image-grid-2x2.html
|
||||
- **의존성:** 없음
|
||||
|
||||
### A-7: table-layout: fixed 적용
|
||||
- **현재:** compare-3col-badge.html에 table-layout 미지정
|
||||
- **CLAUDE.md:** "table-layout: fixed"
|
||||
- **작업:** 테이블 CSS에 table-layout: fixed 추가
|
||||
- **파일:** templates/blocks/tables/compare-3col-badge.html
|
||||
- **의존성:** 없음
|
||||
|
||||
### A-8: container query 폰트 스케일링
|
||||
- **현재:** 표 셀 폰트 크기 고정
|
||||
- **CLAUDE.md:** "container query 폰트 스케일링"
|
||||
- **작업:** @container 규칙으로 표 크기에 따른 폰트 자동 축소
|
||||
- **파일:** templates/blocks/tables/compare-3col-badge.html
|
||||
- **의존성:** A-7
|
||||
|
||||
---
|
||||
|
||||
## Phase B: 누락 기능 구현 (8개)
|
||||
|
||||
> **실행 상세:** [IMPROVEMENT-PHASE-B.md](IMPROVEMENT-PHASE-B.md)
|
||||
|
||||
### B-1: details-block 템플릿 제작
|
||||
- **현재:** BLOCK_SLOTS에 정의만 있고 HTML 템플릿 파일 없음. 렌더링 불가.
|
||||
- **CLAUDE.md:** "HTML 네이티브 `<details>/<summary>` 사용"
|
||||
- **작업:** `<details>/<summary>` 기반 접기/펼치기 블록 템플릿 제작
|
||||
- **파일:** 신규 templates/blocks/emphasis/details-block.html
|
||||
- **의존성:** 없음
|
||||
|
||||
### B-2: 인쇄 시 details 자동 펼침 JS
|
||||
- **현재:** 미구현
|
||||
- **CLAUDE.md:** "인쇄 시 JavaScript 6줄로 자동 펼침"
|
||||
- **작업:** slide-base.html에 `window.onbeforeprint` 핸들러 추가
|
||||
- **파일:** templates/slide-base.html
|
||||
- **의존성:** B-1
|
||||
|
||||
### B-3: catalog에 details-block 등록
|
||||
- **현재:** catalog.yaml에 미등록 → 팀장이 선택 불가
|
||||
- **작업:** id, when, not_for, slots, height_cost 정의하여 등록
|
||||
- **파일:** templates/catalog.yaml
|
||||
- **의존성:** B-1
|
||||
|
||||
### B-4: 1단계 이미지 상세 판단 필드
|
||||
- **현재:** `content_type: "image"` 한 줄만. 개수/소속/핵심여부/텍스트포함 없음.
|
||||
- **CLAUDE.md:** "몇 개인지, 어떤 꼭지 소속인지, 핵심/보조인지, 텍스트 포함 이미지인지"
|
||||
- **작업:** KEI_PROMPT 출력 형식에 images[] 배열 추가 (count, topic_id, role, has_text)
|
||||
- **파일:** src/kei_client.py KEI_PROMPT
|
||||
- **의존성:** 없음
|
||||
|
||||
### B-5: 1단계 표 상세 판단 필드
|
||||
- **현재:** `content_type: "table"` 한 줄만. 행/열 규모 없음.
|
||||
- **CLAUDE.md:** "행/열 규모, 전체 표시 가능 여부"
|
||||
- **작업:** KEI_PROMPT 출력 형식에 tables[] 배열 추가 (rows, cols, fits_single_page)
|
||||
- **파일:** src/kei_client.py KEI_PROMPT
|
||||
- **의존성:** 없음
|
||||
|
||||
### B-6: ~~catalog에 quote-left-border 등록 여부~~ → 제외 확정
|
||||
- **결정 (2026-03-25):** 등록 안 함. 구 블록 제거 방향 유지. 신규 블록(quote-question)만 사용.
|
||||
- **상태:** 해결됨 (작업 불필요)
|
||||
|
||||
### B-7: ~~catalog에 comparison-2col 등록 여부~~ → 제외 확정
|
||||
- **결정 (2026-03-25):** 등록 안 함. 구 블록 제거 방향 유지. 신규 블록(compare-box, comparison-table)만 사용.
|
||||
- **상태:** 해결됨 (작업 불필요)
|
||||
|
||||
### B-8: fallback_layout에서 card-grid → 신규 블록 교체
|
||||
- **현재:** `_fallback_layout()`에서 삭제된 `"card-grid"` 타입 사용 (design_director.py:438)
|
||||
- **작업:** card-image 또는 topic-header 등 신규 블록으로 교체
|
||||
- **파일:** src/design_director.py `_fallback_layout()`
|
||||
- **의존성:** 없음
|
||||
|
||||
---
|
||||
|
||||
## Phase C: 디자인 원칙 위반 수정 (4개)
|
||||
|
||||
> **실행 상세:** [IMPROVEMENT-PHASE-C.md](IMPROVEMENT-PHASE-C.md)
|
||||
|
||||
### C-1: ~~HTML/CSS 블록 배경 그라데이션 제거~~ → CLAUDE.md 원칙 완화
|
||||
- **결정 (2026-03-25):** banner-gradient의 그라데이션은 디자인의 핵심. 코드 수정 대신 CLAUDE.md 원칙을 완화.
|
||||
- **작업:** CLAUDE.md의 "HTML/CSS 블록의 배경 그라데이션 금지" → "디자인 의도가 명확한 블록(배너, 오버레이 등)은 허용" 으로 업데이트
|
||||
- **파일:** CLAUDE.md
|
||||
- **상태:** CLAUDE.md 업데이트만 필요
|
||||
|
||||
### C-2: hover 효과 제거
|
||||
- **현재:** compare-3col-badge.html에 `tr:hover` 배경색 변경
|
||||
- **CLAUDE.md:** "호버 효과 금지"
|
||||
- **작업:** :hover 규칙 삭제
|
||||
- **파일:** templates/blocks/tables/compare-3col-badge.html
|
||||
- **의존성:** 없음
|
||||
|
||||
### C-3: border-radius > 8px 수정
|
||||
- **현재:** quote-question(12px), compare-pill-pair(60px), card-dark-overlay(10px), card-text-grid(12px), compare-3col-badge(25px)
|
||||
- **CLAUDE.md:** "둥근 모서리 과다 사용 금지 (border-radius 최대 8px)"
|
||||
- **작업:** 모두 var(--radius)(6px) 또는 최대 8px로 조정
|
||||
- **파일:** 5개 html 파일
|
||||
- **의존성:** 없음. 단, compare-pill-pair(60px)는 "pill" 모양이 디자인 의도 — 이 블록은 SVG 전환(E-2) 시 해결될 수 있음
|
||||
|
||||
### C-4: circle-gradient box-shadow 2레벨 → 1레벨
|
||||
- **현재:** 2개 box-shadow (0 0 30px + 0 0 60px)
|
||||
- **CLAUDE.md:** "그림자 최소화 (1개 레벨만)"
|
||||
- **작업:** shadow 1개로 축소. 또는 SVG 전환(E-1) 시 filter로 대체
|
||||
- **파일:** templates/blocks/visuals/circle-gradient.html
|
||||
- **의존성:** 없음
|
||||
|
||||
---
|
||||
|
||||
## Phase D: 이미지 처리 — Pillow 도입 (6개)
|
||||
|
||||
> **실행 상세:** [IMPROVEMENT-PHASE-D.md](IMPROVEMENT-PHASE-D.md)
|
||||
> MDX 콘텐츠에 `` 같은 이미지 참조가 포함됨.
|
||||
> 이미지 파일은 로컬 디스크에 존재 (MDX 프로젝트 폴더 기준 상대 경로).
|
||||
> 서버가 localhost에서 돌므로 로컬 파일 접근 가능.
|
||||
|
||||
### D-0: 이미지 경로 입력 UI + API 파라미터 (선행 작업)
|
||||
- **현재:** 프론트엔드에서 텍스트만 전송. 이미지 기준 경로 전달 방법 없음.
|
||||
- **필요 이유:** 이미지 상대 경로(`/assets/images/DX1.png`)를 절대 경로로 해석하려면 base_path 필요.
|
||||
- **작업:**
|
||||
- 프론트엔드(static/index.html): 텍스트에서 `` 패턴 감지 → 발견 시 "이미지 폴더 위치" 입력 팝업 표시
|
||||
- API(src/main.py): `/api/generate` 엔드포인트에 `base_path` 선택 파라미터 추가
|
||||
- 파이프라인(src/pipeline.py): `generate_slide()`에 `base_path` 전달
|
||||
- **파일:** static/index.html, src/main.py, src/pipeline.py
|
||||
- **의존성:** 없음
|
||||
|
||||
### D-1: Pillow 이미지 크기 읽기 유틸리티
|
||||
- **현재:** Pillow import/사용 전무. pyproject.toml에도 없음. src/utils/ 디렉토리 없음.
|
||||
- **CLAUDE.md:** "Pillow Image.open().size (헤더만 읽음)"
|
||||
- **작업:**
|
||||
- pyproject.toml에 `Pillow>=10.0` 추가
|
||||
- 유틸리티 함수: base_path + 상대 경로 → Pillow로 (width, height) 반환
|
||||
- 콘텐츠 텍스트에서 `` 패턴 추출 → 각 이미지 크기 측정
|
||||
- **파일:** pyproject.toml, 신규 src/image_utils.py
|
||||
- **의존성:** D-0 (base_path 전달 체계)
|
||||
|
||||
### D-2: 가로형 이미지(ratio > 1.2) → 전체 너비 배치
|
||||
- **현재:** 비율 기반 배치 판단 없음
|
||||
- **작업:** 파이프라인에서 이미지 크기/비율 정보를 2단계 Step B와 4단계 Sonnet에 전달. 팀장/실무자가 배치 판단.
|
||||
- **파일:** src/pipeline.py 또는 src/design_director.py
|
||||
- **의존성:** D-1
|
||||
|
||||
### D-3: 세로형 이미지(ratio < 0.8) → 텍스트 옆 배치
|
||||
- **현재:** 미구현
|
||||
- **작업:** D-2와 함께 구현. 비율 정보를 프롬프트에 포함하면 AI가 배치 판단.
|
||||
- **파일:** src/design_director.py
|
||||
- **의존성:** D-1
|
||||
|
||||
### D-4: 텍스트 포함 도표 → 과도한 축소 방지
|
||||
- **현재:** 미구현
|
||||
- **작업:** B-4에서 추가한 images[].has_text 정보와 D-1의 크기 정보를 결합. has_text=true이면 "이 이미지는 축소하지 마라" 프롬프트 가이드.
|
||||
- **파일:** src/design_director.py
|
||||
- **의존성:** D-1, B-4 (이미지 상세 판단)
|
||||
|
||||
### D-5: 슬라이드 HTML에 이미지 경로 삽입
|
||||
- **현재:** 이미지 블록(image-row, image-side-text 등)은 src 슬롯에 URL/경로를 넣지만, 실제 이미지 경로가 연결 안 됨.
|
||||
- **작업:** 렌더링된 HTML에서 이미지 상대 경로를 절대 경로 또는 data URI(base64)로 변환하여 다운로드 HTML에서도 이미지 표시.
|
||||
- **파일:** src/renderer.py 또는 src/pipeline.py
|
||||
- **의존성:** D-0, D-1
|
||||
|
||||
---
|
||||
|
||||
## Phase E: visuals 블록 SVG 전환 (3개) — Phase 2 이후 진행
|
||||
|
||||
> **Phase 2 이후로 연기.**
|
||||
> 다른 Claude가 Phase 2에서 `svg_calculator.py`(좌표 계산 모듈) + `renderer.py`에 `_preprocess_svg_data()` + `venn-diagram.html` 동적 템플릿 작업 중.
|
||||
> Phase E는 이 인프라 위에서 나머지 3개 블록을 SVG로 전환하는 작업이므로, Phase 2 완료 후 진행해야 함.
|
||||
>
|
||||
> **활용 방식:** `svg_calculator.py`에 각 블록용 좌표 함수 추가 + `_preprocess_svg_data()`에 블록 등록.
|
||||
>
|
||||
> **P2-D(shrink/rewrite)는 Phase A(A-3/A-4)에서 이미 구현 완료.** 다른 Claude에게 중복 방지 알림 필요.
|
||||
|
||||
### E-1: circle-gradient → SVG
|
||||
- **현재:** CSS border-radius + linear-gradient
|
||||
- **작업:** SVG `<circle>` + `<radialGradient>` + `<text>`로 재제작. `svg_calculator.py`에 함수 추가.
|
||||
- **파일:** templates/blocks/visuals/circle-gradient.html, src/svg_calculator.py
|
||||
- **의존성:** Phase 2 P2-B 완료
|
||||
|
||||
### E-2: compare-pill-pair → SVG
|
||||
- **현재:** HTML div + CSS border-radius: 60px
|
||||
- **작업:** SVG `<rect rx="30">` + `<text>`로 재제작. C-3 border-radius 위반도 해소.
|
||||
- **파일:** templates/blocks/visuals/compare-pill-pair.html
|
||||
- **의존성:** Phase 2 P2-B 완료
|
||||
|
||||
### E-3: process-horizontal → SVG
|
||||
- **현재:** HTML/CSS flexbox + 가상 화살표
|
||||
- **작업:** SVG `<circle>` + `<line>` + `<polygon>` + `<text>`로 재제작. `svg_calculator.py`에 함수 추가.
|
||||
- **파일:** templates/blocks/visuals/process-horizontal.html, src/svg_calculator.py
|
||||
- **의존성:** Phase 2 P2-B 완료
|
||||
|
||||
---
|
||||
|
||||
## Phase F: 향후 — Phase 2 이후 (6개)
|
||||
|
||||
### F-1: Step A를 AI 선택으로 전환
|
||||
- **현재:** 규칙 기반 4줄 코드 (CLAUDE.md에는 "규칙 기반"으로 명시)
|
||||
- **대화에서 요청됨:** AI가 프리셋을 선택하도록 변경
|
||||
- **작업:** select_preset()을 Sonnet 호출로 전환. CLAUDE.md 업데이트.
|
||||
- **의존성:** CLAUDE.md 원칙 변경 합의
|
||||
|
||||
### F-2: Gemini API 배경 생성
|
||||
- **현재:** 미구현
|
||||
- **CLAUDE.md:** "실사 배경: Gemini API (배경 텍스처 전용)"
|
||||
- **작업:** section-title-with-bg 등의 배경 이미지를 Gemini로 생성
|
||||
- **의존성:** Gemini API 키
|
||||
|
||||
### F-3: FAISS 블록 검색
|
||||
- **현재:** 미구현 (PLAN.md DA-20)
|
||||
- **CLAUDE.md:** "변형 40개 이상부터 FAISS 도입 검토"
|
||||
- **작업:** 블록 HTML 구조/용도 임베딩 → FAISS 인덱스 → 검색
|
||||
- **의존성:** DA-19 (변형 40개+)
|
||||
|
||||
### F-4: venn-diagram N개 자동 배치 (cos/sin)
|
||||
- **현재:** Phase 1 — 3개 고정 SVG
|
||||
- **CLAUDE.md:** "Phase 2: N개 자동 배치 (360/N 간격, cos/sin)"
|
||||
- **작업:** renderer에서 items 개수에 따라 좌표 계산 후 템플릿에 전달
|
||||
- **의존성:** 없음
|
||||
|
||||
### F-5: Figma REST API 연동
|
||||
- **현재:** 수동 에셋만 (docs/figma-assets/)
|
||||
- **작업:** Figma API로 에셋 자동 추출
|
||||
- **의존성:** Figma API 키
|
||||
|
||||
### F-6: .astro (Starlight) 출력
|
||||
- **현재:** HTML 다운로드만
|
||||
- **작업:** HTML → .astro 변환 출력 옵션
|
||||
- **의존성:** Starlight 연동 설계
|
||||
|
||||
---
|
||||
|
||||
## Phase별 의존 관계
|
||||
|
||||
```
|
||||
Phase A (슬라이드 품질)
|
||||
├── A-1~A-4: 독립 작업 가능
|
||||
├── A-5: A-1 완료 후
|
||||
├── A-6, A-7: 독립
|
||||
└── A-8: A-7 완료 후
|
||||
|
||||
Phase B (누락 기능)
|
||||
├── B-1~B-5, B-8: 독립
|
||||
├── B-2, B-3: B-1 완료 후
|
||||
└── B-6, B-7: 사용자 결정 대기
|
||||
|
||||
Phase C (디자인 원칙) → 독립. A/B와 병렬 가능.
|
||||
└── C-1: 사용자 결정 대기 (원칙 변경 vs 코드 수정)
|
||||
|
||||
Phase D (Pillow) → D-1 선행, 나머지 순차
|
||||
└── D-4: B-4 완료 후
|
||||
|
||||
Phase E (SVG 전환) → 독립. A/B/C와 병렬 가능.
|
||||
|
||||
Phase F (향후) → Phase A~E 완료 후.
|
||||
└── F-1: CLAUDE.md 합의 후
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 수정 이력
|
||||
|
||||
| 날짜 | 내용 |
|
||||
|------|------|
|
||||
| 2026-03-25 | 초안 작성. CLAUDE.md 전수검토 기반 33개 항목 도출. |
|
||||
Reference in New Issue
Block a user