Figma → 컴포넌트 추출 + 카탈로그 구축 계획
목적
Figma 디자인(바론컨설턴트 홈페이지 기획팀 공유)에서 재사용 가능한 슬라이드 콘텐츠 블록을 추출하고, 디자인 팀장(Sonnet)이 선택할 수 있는 카탈로그로 체계화한다.
현재 상태
보유 자산
| 항목 |
상태 |
위치 |
| Figma API 접근 |
✅ 가능 |
Token: .env |
| 기존 블록 템플릿 7종 |
✅ 완성 |
templates/blocks/ |
| 디자인 토큰 |
✅ 완성 |
static/tokens.css |
| 슬라이드 렌더러 |
✅ 완성 |
src/renderer.py |
| 디자인 팀장 (DA-13) |
❌ todo |
src/design_director.py |
| 블록 카탈로그 |
❌ 없음 |
- |
Figma 파일 구조
기존 블록 vs Figma에서 발견된 패턴
| 패턴 |
기존 블록 |
Figma에서 발견 |
갭 |
| 2단 비교 |
✅ comparison |
✅ |
- |
| 카드 그리드 |
✅ card-grid |
✅ (변형 다수) |
변형 추가 필요 |
| 벤 다이어그램 |
✅ relationship |
✅ |
- |
| 단계 흐름 |
✅ process |
✅ |
- |
| 강조 인용 |
✅ quote-block |
✅ (큰따옴표 장식) |
변형 추가 필요 |
| 결론 바 |
✅ conclusion-bar |
✅ |
- |
| 비교 테이블 |
✅ comparison-table |
✅ |
- |
| 이미지 갤러리 |
❌ |
✅ (2열, 3열, 2x2) |
신규 |
| 타임라인 |
❌ |
✅ (세로 원형 4단계) |
신규 |
| 섹션 타이틀 |
❌ |
✅ (영문+한글 공통 헤더) |
신규 |
| 사례 카드 |
❌ |
✅ (출처+불릿 카드) |
신규 |
| 핵심 지표 |
❌ (정의만) |
✅ (큰 숫자+보조) |
신규 |
| 아이콘 리스트 |
❌ |
✅ (아이콘+제목+설명) |
신규 |
| Hero 섹션 |
❌ |
✅ (배경+원형이미지+텍스트) |
신규 |
| CTA 버튼 바 |
❌ |
✅ (자세히보기 버튼) |
필요 시 |
작업 계획
Phase A: Figma 분석 + 패턴 추출
A-1: Figma 전체 섹션 이미지 렌더링
- 작업: 각 섹션/프레임을 이미지로 렌더링하여 시각적으로 패턴 식별
- 방법: Figma API
/v1/images/{file_key}?ids={node_ids}
- 산출물:
docs/figma-screenshots/ 폴더에 PNG 저장
- 완료 기준: 모든 자세히보기 프레임(8개)의 스크린샷 확보
A-2: Figma 노드 구조 심층 분석
- 작업: 각 프레임의 depth=5 수준까지 노드 트리 분석
- 방법: Figma API
/v1/files/{key}/nodes?ids={ids}&depth=5
- 추출 정보:
- TEXT 노드: 폰트, 크기, 색상, 내용
- FRAME/GROUP: 레이아웃 방식 (auto-layout, constraints)
- RECTANGLE: 배경색, 테두리, 둥근 모서리
- INSTANCE: 재사용 컴포넌트 식별
- 산출물:
docs/figma-analysis/ 폴더에 구조 문서
A-3: 디자인 패턴 분류 + 명명
- 작업: 추출된 시각 요소를 재사용 가능한 블록 단위로 분류
- 기준:
- 2회 이상 반복되는 패턴 → 블록 후보
- 슬롯(교체 가능한 위치)이 명확한 것 → 우선 순위 높음
- 콘텐츠 유형과 매칭되는 것 → 우선 순위 높음
- 산출물: 패턴 목록 + 각 패턴의 Figma 원본 노드 ID
Phase B: HTML/CSS 컴포넌트 제작
B-1: 신규 블록 템플릿 제작 (6~8종)
- 파일:
templates/blocks/{name}.html
- 제작 순서 (우선순위):
section-title.html — 공통 헤더 (모든 슬라이드에서 사용)
example-card.html — 사례 카드 (출처+불릿, 정책 문서 인용)
image-gallery.html — 이미지 갤러리 (2~4장, 근거 자료)
timeline.html — 타임라인 (세로/가로, 연혁/로드맵)
big-number.html — 핵심 지표 (큰 숫자 + 보조 텍스트)
icon-list.html — 아이콘 리스트 (아이콘+제목+설명, 기능 나열)
- 규칙:
- 디자인 토큰(
var(--color-*)) 사용 (하드코딩 색상 금지)
- Jinja2 슬롯 (
{{ variable }}) 형식
<style> 태그를 블록 HTML 안에 포함 (자체 완결)
- Figma 원본과 시각적으로 유사하되 1:1 복제 아님 (디자인 토큰 기준)
B-2: 기존 블록 변형 추가
- 대상:
quote-block.html → quote-block-decorated.html (큰따옴표 ::before/::after 장식)
card-grid.html → card-grid-icon.html (아이콘 강조 변형)
comparison.html → comparison-visual.html (이미지 포함 비교)
- 규칙: 기존 슬롯 구조 유지, CSS만 변형
B-3: slide-base.html 업데이트
- 내용: 신규 블록의 grid-area 지원, 디자인 토큰 추가 (필요 시)
- 주의: 기존 7개 블록의 렌더링이 깨지지 않는지 반드시 검증
Phase C: 카탈로그 구축
C-1: catalog.yaml 생성
- 파일:
templates/catalog.yaml
- 구조:
version: "1.0"
blocks:
# --- 기존 블록 ---
- id: quote-block
name: 강조 인용
visual: "좌측 컬러 라인 + 배경색 + 인용 텍스트"
when: "문제 제기, 핵심 주장, 정의 강조할 때"
not_for: "일반 설명문, 사례 나열"
slots:
required: [quote_text]
optional: [source]
character_limits:
quote_text: 150
source: 50
variations: [default, decorated]
figma_ref: null # 기존 블록은 Figma 이전에 제작됨
# --- 신규 블록 ---
- id: example-card
name: 사례 카드
visual: "제목 + 출처(기관/연도) + 불릿 목록, 테두리 박스. 2~3장 나란히."
when: "정책 문서 인용, 법령/지침 사례, 출처가 명확한 근거 제시"
not_for: "용어 정의, 일반 설명, 비교"
slots:
required: [items[].title, items[].bullets[]]
optional: [items[].source_org, items[].source_year]
character_limits:
title: 30
bullet: 60
variations: [single, 2col, 3col]
figma_ref: "1574:54586 > 2-1_01 > examples-row"
- id: image-gallery
name: 이미지 갤러리
visual: "이미지 2~4장 나란히 + 캡션, 중앙 정렬"
when: "근거 자료 사진, 문서 표지, 현장 사진, 참고 이미지"
not_for: "텍스트 콘텐츠, 다이어그램 (다이어그램은 relationship 사용)"
slots:
required: [images[].src, images[].alt]
optional: [images[].caption]
variations: [2col, 3col, 2x2]
figma_ref: "1574:54586 > 2-1_03 > image grid"
- id: timeline
name: 타임라인
visual: "세로/가로 축 위에 원형 마커 + 연도/제목/설명"
when: "연혁, 로드맵, 정책 시행 일정, 단계별 계획"
not_for: "프로세스 흐름 (순서는 있지만 시간이 아닌 것은 process 사용)"
slots:
required: [events[].year, events[].title]
optional: [events[].description]
character_limits:
title: 25
description: 60
variations: [vertical, horizontal]
figma_ref: "1574:54586 > 2-1_01 > timeline"
- id: big-number
name: 핵심 지표
visual: "큰 숫자(2rem+) + 단위 + 보조 설명. 2~4개 나란히."
when: "KPI, 통계, 목표 수치, 성과 지표"
not_for: "텍스트 설명, 정의"
slots:
required: [metrics[].number, metrics[].label]
optional: [metrics[].unit, metrics[].description]
variations: [2col, 3col, 4col]
figma_ref: null
- id: section-title
name: 섹션 타이틀
visual: "영문 소제목(작은 글씨) + 한글 대제목(큰 글씨), 하단 구분선"
when: "모든 슬라이드 상단, 섹션 시작"
not_for: "본문 콘텐츠 영역"
slots:
required: [title_ko]
optional: [title_en, subtitle]
figma_ref: "공통 > section_title 컴포넌트"
- id: icon-list
name: 아이콘 리스트
visual: "아이콘 + 제목 + 설명이 세로로 나열, 좌측 아이콘 정렬"
when: "기능 나열, 특성 목록, 장점 리스트"
not_for: "비교 (comparison 사용), 순서 (process 사용)"
slots:
required: [items[].icon, items[].title, items[].description]
character_limits:
title: 20
description: 80
variations: [vertical, horizontal, grid]
figma_ref: null
layouts:
- id: "65-35"
name: "6.5:3.5 좌우 분할"
grid_columns: "6.5fr 3.5fr"
when: "좌측 메인 콘텐츠 + 우측 보조/정의"
- id: "50-50"
name: "5:5 균등 분할"
grid_columns: "1fr 1fr"
when: "대등한 비교, 병렬 콘텐츠"
- id: "single"
name: "단일 컬럼"
grid_columns: "1fr"
when: "프로세스 흐름, 타임라인, 단순 구조"
- id: "35-65"
name: "3.5:6.5 좌우 분할"
grid_columns: "3.5fr 6.5fr"
when: "좌측 요약/네비게이션 + 우측 메인 콘텐츠"
C-2: 카탈로그 → 디자인 팀장 프롬프트 연결
- 파일:
src/design_director.py 수정
- 방법:
catalog.yaml 로드 → 블록 목록을 시스템 프롬프트에 삽입
- 프롬프트 구조:
C-3: renderer.py 업데이트
- 내용: 신규 블록 템플릿 로드 지원
- 주의: 기존
BLOCK_SLOTS dict에 신규 블록 추가
충돌 지점 + 리스크 검토
1. Figma 디자인 ≠ 디자인 토큰
| 리스크 |
설명 |
대응 |
| 색상 불일치 |
Figma는 파란 그라데이션 배경 사용, 디자인 토큰은 #2563eb 단색 |
Figma 색상을 참고하되 토큰 체계 우선. 필요 시 토큰 추가 (--color-accent-light 등) |
| 폰트 불일치 |
Figma는 특정 폰트(웹폰트 아닐 수 있음), 토큰은 Pretendard |
Pretendard 유지. Figma 폰트 크기 비율만 참고 |
| 여백 불일치 |
Figma 920px 프레임 vs 슬라이드 1280px |
비율 기반으로 변환 (920:1280 = 0.72배) |
원칙: Figma 디자인을 1:1 복제하지 않는다. 패턴(구조)만 추출하고, 스타일은 디자인 토큰으로 통일한다.
2. 블록 개수 증가 → 디자인 팀장 혼란
| 리스크 |
설명 |
대응 |
| 선택지 과다 |
7개 → 13~15개로 증가 시 Sonnet이 부적절한 블록 선택 가능 |
when + not_for 필드로 선택 기준 명확화. 프롬프트에 "이런 콘텐츠에는 이 블록을 쓰지 마라" 명시 |
| 유사 블록 혼동 |
card-grid vs example-card vs icon-list 구분 |
카탈로그에 각 블록의 차이점 명시. 예: "card-grid는 정의, example-card는 출처 있는 사례, icon-list는 기능 나열" |
대응: catalog.yaml의 not_for 필드가 핵심. "이 블록은 이것에 쓰지 마라"를 명시해야 혼동 감소.
3. 기존 파이프라인 깨짐
| 리스크 |
설명 |
대응 |
| renderer.py 호환성 |
신규 블록 추가 시 기존 렌더링 깨짐 |
기존 7개 블록 테스트 먼저 통과 확인 후 신규 추가 |
| BLOCK_SLOTS 누락 |
design_director.py의 BLOCK_SLOTS에 신규 블록 미등록 |
catalog.yaml에서 자동 로드하는 방식으로 전환 |
| slide-base.html |
grid-template-areas에 신규 area명 미지원 |
동적 생성이므로 문제 없음 (Sonnet이 area명을 직접 지정) |
대응: Phase B 완료 후 기존 테스트 케이스(DA-16) 반드시 재실행.
4. Figma API 제약
| 리스크 |
설명 |
대응 |
| CSS 미제공 |
Figma API는 CSS를 직접 제공하지 않음. 스타일 속성(fill, fontSize 등)만 제공 |
스타일 속성에서 CSS 수동 변환. 복잡한 것은 스크린샷 보고 직접 작성 |
| 이미지 에셋 |
벡터(VECTOR, ELLIPSE)는 PNG로 렌더링 가능하나 CSS 재현 필요 |
단순 도형은 CSS로 재현, 복잡한 것은 PNG export 후 img 태그 |
| INSTANCE 참조 |
Figma 컴포넌트(Instance)의 master 확인 필요 |
GET /v1/files/{key}/components로 마스터 컴포넌트 조회 |
| Rate Limit |
Figma API rate limit 존재 |
한 번에 대량 호출 자제, 결과 캐싱 |
5. Starlight(.astro) 연결 시 충돌
| 리스크 |
설명 |
대응 |
| CSS 변수 충돌 |
Starlight 자체 CSS 변수(--sl-*)와 디자인 토큰(--color-*) 충돌 |
네임스페이스 분리: --da-color-* 접두사 사용 검토 |
| 폰트 로딩 |
.astro에서 Pretendard CDN 로드 필요 |
<style is:global>에 @import 포함 |
<style> 인라인 |
현재 렌더러가 CSS를 인라인하는데, .astro에서 Starlight CSS와 섞임 |
.astro 출력 시 scoped style 또는 is:global + 높은 specificity |
대응: .astro 출력은 Phase C 이후 별도 태스크로. 현재는 독립 HTML 출력에 집중.
6. 유사 프로젝트 사례에서 발견된 문제
| 사례 |
문제 |
교훈 |
| SlideSpeak |
16개 레이아웃으로 시작했으나 실제 콘텐츠 다양성 커버 못함 |
블록을 조합하는 방식이 고정 레이아웃보다 유연 (현재 방식 유지) |
| PPTAgent (EMNLP 2025) |
레퍼런스 슬라이드 클러스터링 시 과소/과다 분류 문제 |
블록 수를 10~15개로 제한. 너무 세분화하면 AI 선택이 어려워짐 |
| Beautiful.ai |
300개 템플릿 중 실제 사용은 20개 |
처음부터 많이 만들지 않기. 실제 사용 빈도 보고 추가 |
| InfoDesignLM |
텍스트만으로 레이아웃 생성 시 콘텐츠 양 ↔ 공간 불일치 |
character_limits를 카탈로그에 명시, 텍스트 편집자가 강제 준수 |
작업 순서 (의존 관계)
예상 소요
| Phase |
작업 |
규모 |
| A (분석) |
Figma 스크린샷 + 노드 분석 + 패턴 분류 |
탐색/조사 |
| B (제작) |
신규 블록 6~8종 + 변형 3종 + base 업데이트 |
구현 (핵심) |
| C (카탈로그) |
catalog.yaml + 팀장 프롬프트 + renderer 업데이트 |
연결/통합 |
핵심 원칙: Phase A에서 패턴을 정확히 분류하지 않으면 Phase B에서 쓸모없는 블록을 만들게 된다. 분석 먼저, 제작은 그 다음.
산출물 목록
금지 사항
- Figma 디자인을 1:1 복제하지 않는다 (패턴만 추출, 스타일은 토큰 기준)
- 기존 7개 블록 템플릿을 수정하지 않는다 (신규/변형은 별도 파일)
- 한 번에 모든 블록을 만들지 않는다 (A-3 분류 결과를 보고 우선순위 재조정)
- catalog.yaml 없이 블록을 추가하지 않는다 (카탈로그 미등록 = 디자인 팀장이 모름)
- Kei Persona Agent 코드를 수정하지 않는다