"""3가지 접근법 비교: 같은 콘텐츠, 다른 생성 방식. 접근 A: Few-Shot 직접 생성 — Claude가 디자인 토큰 안에서 HTML 직접 작성 접근 B: 레이아웃 프리미티브 조합 — 15개 기본 요소를 조합 접근 C: 참조 기반 생성 — ideal_v2를 참조하여 구조 유지하되 콘텐츠만 교체 Kei API 불필요 — 순수 렌더링만. """ from __future__ import annotations import asyncio, json, sys, base64 from pathlib import Path ROOT = Path(__file__).parent.parent sys.path.insert(0, str(ROOT)) # ═══════════════════════════════════════ # 공통 디자인 토큰 (3가지 접근 모두 이 토큰만 사용) # ═══════════════════════════════════════ DESIGN_TOKENS_CSS = """ :root { --color-primary: #1e293b; --color-accent: #2563eb; --color-accent-light: #93c5fd; --color-bg: #ffffff; --color-bg-subtle: #f8fafc; --color-bg-dark: #1e293b; --color-bg-dark-deep: #0f172a; --color-border: #e2e8f0; --color-danger: #dc2626; --color-warning: #fbbf24; --color-text: #1e293b; --color-text-secondary: #64748b; --color-text-light: #94a3b8; --color-text-on-dark: #e2e8f0; --color-text-on-accent: #ffffff; --font-title: 28px; --font-section: 14px; --font-body: 13px; --font-small: 11px; --font-caption: 10px; --weight-normal: 400; --weight-medium: 500; --weight-bold: 700; --weight-black: 900; --spacing-page: 36px 40px 24px; --spacing-section: 16px; --spacing-block: 12px; --spacing-inner: 10px; --spacing-small: 6px; --radius: 8px; --radius-small: 6px; --line-height: 1.6; } """ SLIDE_BASE_CSS = """ @import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css'); * { margin: 0; padding: 0; box-sizing: border-box; } .slide { width: 1280px; height: 720px; overflow: hidden; background: var(--color-bg); font-family: 'Pretendard Variable', sans-serif; color: var(--color-text); font-size: var(--font-body); line-height: var(--line-height); word-break: keep-all; display: grid; grid-template-areas: 'header header' 'body sidebar' 'footer footer'; grid-template-columns: 65fr 35fr; grid-template-rows: auto 1fr auto; gap: var(--spacing-section); padding: var(--spacing-page); } .header { grid-area: header; font-size: var(--font-title); font-weight: var(--weight-black); color: var(--color-primary); border-bottom: 3px solid var(--color-accent); padding-bottom: 8px; } .body { grid-area: body; display: flex; flex-direction: column; gap: var(--spacing-block); overflow: hidden; } .sidebar { grid-area: sidebar; display: flex; flex-direction: column; gap: var(--spacing-block); border-left: 1px solid var(--color-border); padding-left: 20px; overflow: hidden; } .footer { grid-area: footer; background: linear-gradient(135deg, #006aff, #00aaff); border-radius: var(--radius); padding: 14px 30px; text-align: center; color: var(--color-text-on-accent); } .footer-text { font-size: 15px; font-weight: var(--weight-bold); } .footer-sub { font-size: var(--font-small); opacity: 0.85; margin-top: 2px; } """ # ═══════════════════════════════════════ # 접근 A: Few-Shot 직접 생성 # Claude가 디자인 토큰만 보고 자유롭게 HTML 구성 # (여기서는 "Claude가 만들었을 법한" 결과를 시뮬레이션) # ═══════════════════════════════════════ APPROACH_A_HTML = f""" 접근 A
건설산업 DX의 올바른 이해

현실 — 용어의 혼용

건설산업에서 DX와 BIM이 동일 개념으로 인식되고 있다. DX는 산업 전반의 프로세스를 혁신하는 상위개념이며, BIM은 3차원 모델 기반의 정보 관리 도구로서 DX의 하위 기술에 해당한다.

스마트 건설 활성화 방안 (2022.07)
추진과제: 건설산업 디지털화
실행과제: BIM 전면 도입, BIM 전문인력 양성
제7차 건설기술진흥 기본계획 (2023.12)
추진방향: 디지털 전환을 통한 스마트 건설 확산
추진과제: BIM 도입으로 건설산업 디지털화
DX와 핵심기술의 올바른 관계
DX — 디지털 전환 (상위개념)
BIM, GIS, 디지털 트윈 등 핵심기술의 융합을 통해서만 실현 가능
G
GIS 지리적 데이터를 공간 분석하여 시각적으로 표현, 위치기반 정보 제공
B
BIM 시설물 생애주기 정보를 3차원 모델 기반으로 통합·관리하는 도구
T
디지털 트윈 현실 세계의 물리적 객체를 디지털 환경에 동일하게 구현

BIM ≠ DX — BIM은 DX를 실현하기 위한 핵심 기술 중 하나일 뿐이다

""" # ═══════════════════════════════════════ # 접근 B: 레이아웃 프리미티브 조합 # 15개 기본 요소 중 선택하여 조합 # ═══════════════════════════════════════ APPROACH_B_HTML = f""" 접근 B
건설산업 DX의 올바른 이해
현실 — 용어의 혼용
건설산업에서 DX와 BIM이 동일 개념으로 인식되고 있다. DX는 상위개념이며 BIM은 하위 기술에 해당한다.
스마트건설 활성화 방안 (2022.07)
제7차 건설기술진흥 기본계획 (2023.12)
추진과제: 건설산업 디지털화
추진방향: 디지털 전환을 통한 스마트 건설 확산
실행과제: BIM 전면 도입, 전문인력 양성
추진과제: BIM 도입으로 건설산업 디지털화
DX와 핵심기술의 올바른 관계
G
GIS 지리적 데이터를 공간 분석하여 시각적으로 표현, 위치기반 정보 제공
B
BIM 시설물 생애주기 정보를 3차원 모델 기반으로 통합·관리하는 도구
T
디지털 트윈 현실 세계의 물리적 객체를 디지털 환경에 동일하게 구현

BIM ≠ DX — BIM은 DX를 실현하기 위한 핵심 기술 중 하나일 뿐이다

""" # ═══════════════════════════════════════ # 접근 C: 참조 기반 생성 # ideal_v2의 구조를 참조하되, 디자인 토큰으로 스타일 통일 # + 포함관계를 더 명확하게 (DX 큰 원 안에 3개) # ═══════════════════════════════════════ APPROACH_C_HTML = f""" 접근 C
건설산업 DX의 올바른 이해

현실 — 용어의 혼용

건설산업에서 DX와 BIM이 동일 개념으로 인식되고 있다. DX는 산업 전반의 프로세스를 혁신하는 상위개념이며, BIM은 하위 기술에 해당한다.

스마트 건설 활성화 방안 (2022.07)
추진과제: 건설산업 디지털화
실행과제: BIM 전면 도입, BIM 전문인력 양성
제7차 건설기술진흥 기본계획 (2023.12)
추진방향: 디지털 전환을 통한 스마트 건설 확산
추진과제: BIM 도입으로 건설산업 디지털화
DX와 핵심기술의 올바른 관계
DX — 디지털 전환 (상위개념)
업무방식과 가치 창출 구조를 근본적으로 전환하는 과정
G
GIS 지리적 데이터를 공간 분석, 위치기반 정보 제공
B
BIM 시설물 생애주기 정보를 3차원 모델로 통합·관리
T
디지털 트윈 현실 객체를 디지털 환경에 동일하게 구현

BIM ≠ DX — BIM은 DX를 실현하기 위한 핵심 기술 중 하나일 뿐이다

""" async def main(): from src.slide_measurer import measure_rendered_heights, capture_slide_screenshot out_dir = ROOT / "data" / "runs" / "3approaches" out_dir.mkdir(parents=True, exist_ok=True) for name, html in [("A_fewshot", APPROACH_A_HTML), ("B_primitives", APPROACH_B_HTML), ("C_reference", APPROACH_C_HTML)]: print(f"\n=== 접근 {name} ===") m = await asyncio.to_thread(measure_rendered_heights, html) s = await asyncio.to_thread(capture_slide_screenshot, html) (out_dir / f"{name}.html").write_text(html, encoding="utf-8") if s: (out_dir / f"{name}.png").write_bytes(base64.b64decode(s)) slide = m.get("slide", {}) print(f" slide: {slide.get('scrollHeight', 0)}px / 720px {'✅' if not slide.get('overflowed') else '❌'}") print(f"\n결과물: {out_dir}") print(" A_fewshot.png — 접근 A: Claude가 디자인 토큰 안에서 자유 생성") print(" B_primitives.png — 접근 B: 15개 프리미티브 조합") print(" C_reference.png — 접근 C: ideal_v2 참조 기반 + 더 큰 포함관계 시각화") if __name__ == "__main__": import logging logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s", datefmt="%H:%M:%S") logging.getLogger("selenium").setLevel(logging.WARNING) logging.getLogger("urllib3").setLevel(logging.WARNING) asyncio.run(main())