Figma 퍼블리싱 파이프라인 01. 자동화 전략 & 기술 선택
외주 프로젝트에서 반복되는 Figma → 코드 퍼블리싱을 자동화하기로 결정했다. 이 여정의 첫 번째 버전이다. 당시에는 MCP를 쓸지, REST API를 쓸지 몰라서 두 방식을 직접 비교해보고, 최종적으로 Python + REST API 기반 파이프라인으로 결정했다.
문제 정의
프론트엔드 개발자로 일하다 보면 이런 순간이 반복된다.
"Figma 링크 공유드렸어요. 이번 주 안에 퍼블리싱 부탁드립니다."
그러면 개발자는 Figma를 열고, 색상을 눈으로 확인하고, 폰트 사이즈를 하나씩 읽고, 아이콘을 export하고, 이미지를 다운받고... 이 과정을 수작업으로 반복한다.
현재 진행 중인 외주 프로젝트에서 이 반복이 너무 잦았다. 관리자 대시보드 페이지만 수십 개인데, 매번 같은 수작업을 하고 있으니 "이걸 자동화할 수 있지 않을까?" 하는 생각이 들었고, 실제로 만들어서 적용해보고 있다.
Claude(AI), Python 스크립트, Figma API를 조합해서 Figma URL 하나를 넣으면 코드가 나오는 시스템을 구성했다.
전체 파이프라인 한눈에 보기
핵심 원칙: AI(LLM)는 코드 생성(PHASE 2)에만 사용한다. 나머지는 Python이 처리해서 비용과 시간을 최소화한다.
기술 선택: MCP vs REST API
Figma에서 코드를 뽑아내는 방법이 두 가지가 됐다. Claude Code에서 get_design_context를 호출하는 MCP 방식과, Figma REST API를 직접 호출하는 방식. 둘 다 "Figma 데이터를 가져온다"고 하지만, 실제로 돌려보면 돌아오는 데이터의 성격이 완전히 다르다.
MCP의 구조적 한계
MCP가 반환하는 코드는 Tailwind 클래스로 표현된 근사값이다. p-4는 16px인데, 실제 Figma 값이 12px인 경우도 p-3이 아니라 p-4로 나올 수 있다. Tailwind의 4px 그리드로 반올림되기 때문이다.
반면 REST API의 paddingTop, paddingLeft 필드는 픽셀 단위 정확한 값이다.
더 심각한 문제:
1. 토큰 바인딩 정보 부재
디자인 시스템에서 가장 중요한 건 색상이 어떤 시맨틱 토큰으로 연결돼 있는가다. #3B82F6을 하드코딩하면 안 되고, color.primary.500이나 var(--color-primary)로 써야 한다.
REST API 응답에는 boundVariables 필드가 있어서 "이 노드의 이 fill이 어떤 변수에 바인딩되어 있는가"를 정확히 알 수 있다. MCP의 get_variable_defs는 변수 이름↔값 매핑은 조회 가능하지만 노드별 바인딩 정보는 제공하지 않는다.
2. 숨겨진 상태 미포함
컴포넌트에는 기본 상태(default), 호버(hover), 비활성(disabled) 등 여러 상태가 있다. Figma에서는 이것들이 visible: false 레이어나 componentProperties로 표현된다.
MCP의 get_design_context는 현재 보이는 상태 하나만 반환한다. REST API로 전체 노드 트리를 받으면 모든 상태가 다 있다. 조건부 렌더링을 구현할 때 이 차이가 결정적이다.
3. 응답 잘림 문제
복잡한 컴포넌트에서 get_design_context의 응답이 잘리는 경우가 있다. REST API는 depth 파라미터로 조회 깊이를 조절하고, 잘린 노드를 감지해서 추가 요청으로 채울 수 있다.
REST API가 주는 것
정리하면 REST API는 원시 데이터를 준다.
- 모든 레이어 (visible: false 포함)
- 픽셀 단위 정확한 수치
- boundVariables로 토큰 연결 정보
- componentProperties로 모든 UI 상태
- 재귀적으로 깊은 노드까지 순회 가능
토큰 비용 비교
MCP 방식 (per 노드, 추정):
get_design_context 호출 → ~1K (tool call)
전처리된 결과 수신 → ~5~15K (코드 힌트 + 메타)
합계: ~6~16K tokens
REST API + Claude 직접 해석 (per 노드, 추정):
curl API 호출 + JSON 수신 → ~30~80K (raw 노드 데이터)
Claude가 JSON 파싱 → ~5K (추론)
합계: ~35~85K tokens
REST API + Python 전처리 (per 노드, 추정):
Python이 API 호출 + 파싱 → 0 tokens (Claude 밖에서 처리)
구조화된 스펙만 Claude에 전달 → ~3~8K tokens
합계: ~3~8K tokensMCP가 토큰 효율적으로 보이지만, Python 전처리 파이프라인을 쓰면 REST API 방식이 오히려 더 적게 소모한다. 정확도와 토큰 효율 모두 잡는 셈이다.
최종 결정: Python + REST API
| MCP | REST API | |
|---|---|---|
| 수치 정확도 | 근사값 | 픽셀 단위 정확 |
| 토큰 역추적 | 변수 정의 조회 가능, 노드별 바인딩 미제공 | boundVariables로 노드별 바인딩 |
| 숨겨진 레이어 | 미포함 | 전체 포함 |
| 조건부 UI 상태 | 현재 상태만 | 모든 상태 |
| 스크린샷 | 있음 | 없음 |
| 응답 잘림 가능성 | 있음 | 제어 가능 |
| 토큰 비용 (Python 전처리) | 응답 크기만큼 소모 | 0 (Python으로 처리) |
프로덕션 퍼블리싱 파이프라인에서는 정확한 스펙 수집은 REST API, 시각적 확인과 코드 생성 보조는 MCP를 조합하는 방식을 택했다.
이 버전에서 배운 것
-
정확도 > 편리성: 근사값으로 시작하면 나중에 수정이 더 많아진다. 처음부터 정확한 데이터를 기반으로 설계해야 한다.
-
AI는 코드 생성에만: 색상 매핑, 아이콘 분류, 이미지 다운로드처럼 규칙이 명확한 작업은 Python이 한다. AI는 규칙이 명확하지 않은 "코드 설계와 구현"에만 투입한다.
-
토큰 비용은 구조의 문제: 모델이 효율적이어야 한다는 게 아니라, 어떤 구조로 만드는지가 결정적이다.
다음 버전에서는 이 기반 위에 스킬 시스템을 구축하고, 엣지케이스들을 처리했다.