포함 내용: - Phase P/Q/R/S 설계 문서 (IMPROVEMENT-PHASE-*.md) - 영역별 검증 스크립트 (scripts/verify_*.py, test_*.py) - 블록 템플릿 추가 (cards, emphasis 변형) - 코드 수정: block_search, content_editor, design_director, slide_measurer - catalog.yaml 블록 목록 업데이트 - CLAUDE.md, PROGRESS.md, README.md 업데이트 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
11 KiB
11 KiB
Phase R: 하이브리드 블록 시스템 — 기존 블록 활용 + 변형 + 자유 생성
작성일: 2026-03-30 상태: 설계 확정, 실행 대기 선행: Phase Q (제약 기반 블록 선택 + 글자수 예산) 코드 완료 근거: Phase Q 6차 테스트 + 하이브리드 시뮬레이션 검증
1. 배경: 왜 Phase R이 필요한가
Phase Q까지의 성과
- ✅ 유령 블록 제거 (catalog 검증)
- ✅ relation_type → 카테고리 결정론적 매핑
- ✅ 글자수 예산 사전 계산
- ✅ fill_candidates topic별 개별 호출 복원
- ✅ 비전 모델 품질 게이트
- ✅ overflow 수학적 조정 (LaTeX 글루 모델)
Phase Q에서 해결 못한 문제
- ❌ 블록이 콘텐츠 구조에 안 맞는 경우 — 38개 고정 블록 중 "정확히 맞는 것"이 없을 때 억지로 끼워 맞춤
- ❌ topic 1개 = 블록 1개 고정 규칙 — topic 합침/분리 불가
- ❌ 콘텐츠 전달 의도 반영 부족 — "이해시키는 시각화"가 아닌 "텍스트 나열"
하이브리드 시뮬레이션으로 증명된 것
DX 시행 목표 콘텐츠로 테스트한 결과:
| 블록 | 용도 | 활용 방식 | 블록 재사용률 |
|---|---|---|---|
card-icon-desc |
목표 3카드 | 기존 블록 100% | 그대로 |
dark-bullet-list |
프로세스 변화 | 기존 색상/구조 + Before→After 변형 | 80% |
divider-text |
섹션 구분 | 기존 블록 100% | 그대로 |
table-simple-striped |
주체별 효과 | 기존 블록 100% | 그대로 |
banner-gradient |
결론 | 기존 블록 100% | 그대로 |
결론: 38개 블록의 80%는 그대로 사용 가능. 빠진 것은 "변형 능력" 1가지.
2. 핵심 원칙
블록 선택 → 맞는 블록 있으면 그대로 사용 (기존 Phase Q)
→ 80% 맞는 블록 있으면 변형해서 사용 (Phase R 추가)
→ 전혀 안 맞으면 디자인 토큰 안에서 자유 생성 (Phase R 추가)
3단계 렌더링 우선순위
| 우선순위 | 방식 | 조건 | 품질 안정성 |
|---|---|---|---|
| 1순위 | 기존 블록 그대로 | catalog에 정확히 맞는 블록이 있을 때 | 가장 높음 (검증된 템플릿) |
| 2순위 | 기존 블록 변형 | 80% 맞는 블록 + variant로 보완 | 높음 (기존 CSS 기반) |
| 3순위 | 디자인 토큰 기반 자유 생성 | 어떤 블록으로도 안 맞을 때 | 중간 (토큰 제약 + 검증 필요) |
3. 구체적 설계
R-1: catalog.yaml에 variants 메타데이터 추가
기존 블록에 "변형 가능한 형태"를 정의한다. 변형은 기존 CSS를 유지하면서 내부 구조만 달라지는 것.
- id: dark-bullet-list
category: emphasis
# ... 기존 필드 유지 ...
variants:
- id: default
description: 기존 불릿 나열
template: blocks/emphasis/dark-bullet-list.html
- id: before-after
description: Before→After 2열 구조 (프로세스 변화)
template: blocks/emphasis/dark-bullet-list--before-after.html
when: "기존 방식 → 새 방식으로의 전환/변화를 보여줄 때"
- id: card-icon-desc
category: cards
variants:
- id: default
description: 아이콘 + 제목 + 설명 (기본)
- id: compact
description: 아이콘 축소, 설명 2줄 제한 (높이 부족 시)
- id: horizontal
description: 아이콘-제목-설명 가로 배치 (좁은 공간)
- id: comparison-2col
category: emphasis
variants:
- id: default
description: 좌우 텍스트 비교
- id: cards-in-container
description: 큰 박스 안에 카드 N개 (포함 관계 시각화)
when: "hierarchy/inclusion — A 안에 B,C,D가 포함됨을 보여줄 때"
- 파일:
templates/catalog.yaml - 변경: 기존 블록에
variants[]필드 추가 - 변형 템플릿:
blocks/{category}/{block-id}--{variant-id}.html파일 추가
R-2: variant 템플릿 제작
블록별 변형 HTML 템플릿을 추가한다. 기존 블록의 CSS(색상, 배경, radius 등)를 그대로 사용하고 내부 구조만 변경.
우선 제작 대상 (시뮬레이션에서 검증된 변형):
| 블록 | variant | 용도 |
|---|---|---|
dark-bullet-list |
before-after |
프로세스 변화 (Before→After 2열) |
comparison-2col |
cards-in-container |
포함 관계 (DX ⊃ GIS+BIM+DT) |
card-icon-desc |
compact |
높이 부족 시 축소 |
card-numbered |
horizontal |
사례 가로 비교 |
- 파일:
templates/blocks/{category}/에--{variant}.html추가 - 원칙: 기존 블록의 CSS 클래스/색상을 재사용. 새 CSS는 최소한만 추가.
R-3: block_selector.py에 variant 선택 로직 추가
블록 선택 시 variant도 함께 결정. Kei에게 "이 블록의 어떤 변형이 적합한가"를 함께 제시.
# block_selector.py 수정
def select_block_candidates(topic, container_spec, used_blocks, catalog):
# ... 기존 필터링 로직 유지 ...
# 각 후보 블록의 variants도 함께 반환
for block in candidates:
variants = block.get("variants", [{"id": "default"}])
# expression_hint와 매칭되는 variant 우선 정렬
block["_available_variants"] = variants
return candidates
R-4: Kei 블록 선택 프롬프트에 variant + expression_hint 전달
Q-4 프롬프트를 확장하여 variant 선택과 expression_hint를 포함.
## 후보 블록
1. dark-bullet-list (다크 배경 불릿)
변형:
- default: 기존 불릿 나열
- before-after: Before→After 2열 구조
★ 표현 의도: "기존 방식에서 새 방식으로의 전환을 보여주는 구조"
→ before-after 변형이 적합
## 선택 (JSON)
{"block_id": "dark-bullet-list", "variant": "before-after", "reason": "..."}
R-5: renderer.py에 variant 렌더링 지원
variant가 지정되면 해당 변형 템플릿을 사용하여 렌더링.
# renderer.py 수정
def _resolve_template_path(env, block_type, variant="default"):
if variant and variant != "default":
# 변형 템플릿 우선
variant_path = f"blocks/{category}/{block_type}--{variant}.html"
if template_exists(env, variant_path):
return variant_path
# 기존 템플릿 fallback
return f"blocks/{category}/{block_type}.html"
R-6: 3순위 자유 생성 (디자인 토큰 기반)
어떤 블록+변형으로도 안 맞을 때, AI가 디자인 토큰 안에서 HTML을 직접 생성.
# 자유 생성 조건
if not suitable_block_found:
# 디자인 토큰 + 3-5개 예시 슬라이드를 프롬프트에 포함
# AI가 HTML 생성
# Selenium으로 검증
html = await generate_free_block_html(topic, container_spec, design_tokens)
제약 사항:
- 디자인 토큰(CSS 변수)만 사용 가능 — 하드코딩 색상/폰트 금지
- 감사 스크립트로 토큰 위반 검출 (Atlassian 방식)
- Selenium 측정으로 overflow 검증
- 비전 모델 품질 게이트 통과 필수
R-7: expression_hint를 fill_candidates에 전달
1단계에서 Kei가 판단한 expression_hint를 편집자(fill_candidates)에게 전달하여 텍스트 구성에 반영.
# fill_candidates 프롬프트에 추가
section += f"\n ★ 표현 의도: {topic.get('expression_hint', '')}"
section += f"\n ★ 변형: {block.get('_variant', 'default')}"
4. 실행 계획
의존 관계
R-1 (catalog variants) ──→ R-2 (variant 템플릿) ──→ R-5 (renderer variant 지원)
──→ R-3 (selector variant)──→ R-4 (Kei 프롬프트 확장)
──→ R-7 (expression_hint 전달)
R-6 (자유 생성) ← R-5 완료 후 독립 작업
우선순위
| 순서 | 스텝 | 내용 | 효과 |
|---|---|---|---|
| 1 | R-1 | catalog에 variants 추가 | 데이터 기반 |
| 2 | R-2 | before-after, cards-in-container 템플릿 제작 | 시뮬레이션에서 검증된 변형 우선 |
| 3 | R-5 | renderer variant 렌더링 | 변형 블록이 실제로 렌더링 |
| 4 | R-3 | block_selector variant 필터링 | variant 후보 제시 |
| 5 | R-4 | Kei 프롬프트 확장 | variant + expression_hint |
| 6 | R-7 | fill_candidates에 expression_hint 전달 | 텍스트 구성 개선 |
| 7 | R-6 | 자유 생성 (3순위) | 블록으로 안 맞을 때 대비 |
수정 파일
| 파일 | 변경 내용 |
|---|---|
templates/catalog.yaml |
variants[] 필드 추가 |
templates/blocks/emphasis/dark-bullet-list--before-after.html |
신규 |
templates/blocks/emphasis/comparison-2col--cards-in-container.html |
신규 |
templates/blocks/cards/card-icon-desc--compact.html |
신규 |
templates/blocks/cards/card-numbered--horizontal.html |
신규 |
src/block_selector.py |
variant 필터링 로직 추가 |
src/kei_client.py |
Q-4 프롬프트에 variant + expression_hint |
src/renderer.py |
variant 템플릿 해석 |
src/content_editor.py |
fill_candidates에 expression_hint 전달 |
5. 기대 효과
| 지표 | Phase Q (현재) | Phase R (목표) |
|---|---|---|
| 블록 적합도 | 60% (억지로 끼워 맞춤) | 90%+ (변형으로 맞춤) |
| 콘텐츠 구조 반영 | 낮음 (텍스트 나열) | 높음 (Before→After, 포함관계 등) |
| 블록 재사용률 | 38개 중 5-6개 사용 | 38개 + variants로 실질 50+ |
| 자유 생성 비율 | 0% | 5-10% (안 맞을 때만) |
| 텍스트 보존도 | Phase P 수준 (fill_candidates) | 동일 유지 |
6. Phase P → Q → R 전체 흐름 정리
Phase P (20점): FAISS+Opus → 블록 선택 → 다후보 렌더링 비교 → 느리고 부정확
↓
Phase Q (77점): relation_type → 결정론적 필터링 → 예산 사전 계산 → 빠르고 정확
→ 하지만 "맞는 블록이 없으면 억지로 끼워 맞춤"
↓
Phase R (목표): Phase Q 유지 + variant 변형 + expression_hint 전달
→ 기존 블록 80% 활용 + 20% 변형/자유 생성
→ 콘텐츠 전달 의도에 맞는 시각화
7. 검증된 시뮬레이션 결과
콘텐츠 1: 건설산업 DX의 올바른 이해 (포함 관계)
ideal_v2+3approaches폴더: 접근 A, C가 우수comparison-2col--cards-in-container변형이 핵심 (DX ⊃ GIS+BIM+DT)
콘텐츠 2: DX 시행 목표 및 기대 효과 (목표/프로세스)
hybrid_simulation폴더: 블록 80% 활용 확인dark-bullet-list--before-after변형이 핵심 (프로세스 변화)card-icon-desc기존 블록 그대로 사용 (목표 3카드)table-simple-striped기존 블록 그대로 사용 (주체별 효과)
공통 확인
- 720px overflow 없음
- 디자인 토큰(색상, 폰트, 간격) 일관성 유지
- sidebar 프리셋 적절히 작동
8. 참고: 조사 기반 근거
| 출처 | 적용한 인사이트 |
|---|---|
| Atlassian + LLM | CSS 변수로 제한 → "10번째도 1번째와 동일 품질" |
| frontend-slides (11.5K stars) | 디자인 토큰 + 예시 기반 → 프로덕션 품질 HTML 생성 |
| TechGrid 인터뷰 | "모델의 자유도를 줄이고 모든 것을 검증" |
| VASCAR | 생성 → 렌더링 → 비전 모델 평가 → 교정 |
| Beautiful.ai | 템플릿 + 제약 엔진 (자동 조정 규칙) |
| AutoPresent (CVPR 2025) | 코드 API 기반 조합 생성 |