AI가 계속해서 잘못된 디자인 토큰 (Design Tokens)을 생성하는 이유와 Figma API를 통해 이를 해결한 방법
요약
AI가 디자인 시스템의 시맨틱 토큰을 정확히 매핑하지 못해 발생하는 불일치 문제를 분석합니다. 프롬프트 엔지니어링 대신 Figma REST API를 활용하여 결정론적 데이터를 구조적으로 가져오는 해결책을 제시합니다.
핵심 포인트
- AI는 시각적 구조는 잘 파악하지만 시맨틱 토큰 매핑에는 한계가 있음
- 프롬프트 개선만으로는 디자인 시스템의 정밀한 값 오류를 해결할 수 없음
- Figma API를 통해 정확한 디자인 데이터를 추출하는 구조적 접근 필요
AI 디자인 시스템 (Design System) 출력값은 기본적으로 근사치에 불과합니다. 잘못된 테두리 반경 (Border Radii), 가공되지 않은 헥사 값 (Hex Values), 60개의 컴포넌트에 걸쳐 일관되지 않은 토큰들. 해결책은 더 나은 프롬프트 (Prompt)가 아닙니다. Figma의 REST API를 사용하여 이를 정확하게 만든 구조적 변화를 소개합니다.
AI가 생성한 컴포넌트에서 동일한 테두리 반경 (Border Radius) 실수를 수동으로 네 번째 수정했을 때, 나는 멈춰서 왜 이런 일이 계속 발생하는지 자문했습니다.
"어떤 프롬프트가 이것을 해결할 수 있을까?"가 아닙니다. 더 깊은 질문은 이것이었습니다: 왜 내가 시도한 모든 AI 도구들은 구조는 맞게 잡으면서 값 (Value)은 틀리게 가져오는 걸까?
버튼은 정확했습니다. 베리언트 (Variants)도 있었습니다. 레이아웃은 Figma 명세 (Spec)와 일치했습니다. 하지만 borderRadius: 8이어야 할 것이 borderRadius: '8px'로 되어 있었습니다. 명세에는 6이라고 되어 있는데 간격 (Spacing)이 8이었습니다. #3B82F6 색상이 semantic.button.primary가 있어야 할 자리에 놓여 있었습니다.
이 중 어느 것도 빌드 (Build)를 깨뜨릴 정도로 틀린 것은 아니었습니다. 하지만 모두 디자인 시스템 (Design System)을 깨뜨리는 방식으로 틀려 있었습니다.
이 벽에 충분히 부딪힌 후, 나는 문제가 AI가 아니라는 것을 깨달았습니다. 문제는 내가 AI에게 던지는 질문이었습니다.
왜 AI는 계속해서 잘못된 Figma 디자인 토큰 (Design Tokens)을 생성하는가
AI 도구에 Figma 스크린샷을 주고 컴포넌트를 생성해 달라고 요청하면, AI는 합리적인 행동을 합니다. 즉, 보이는 것을 해석하는 것입니다.
구조, 레이아웃, 계층 구조 (Hierarchy) — AI는 이 대부분을 정확하게 파악합니다. 하지만 제대로 할 수 없는 것은 토큰 매핑 (Token Mapping)입니다.
AI는 당신의 시맨틱 토큰 (Semantic Token) 파일을 알지 못합니다. #3B82F6이 코드베이스에서 semantic.button.primary에 매핑된다는 사실도 모릅니다. 당신의 MUI 설정이 숫자 형태의 테두리 반경 (Border Radii)에 4를 곱한다는 사실도 모릅니다. 이는 borderRadius: 8이 8px 대신 32px로 렌더링된다는 것을 의미합니다.
그래서 AI는 근사치를 내놓습니다. 실제 사례는 다음과 같습니다:
| AI가 생성한 결과 | 명세(Spec) 요구사항 | 틀린 이유 |
|---|---|---|
borderRadius: 8 | borderRadius: '8px' | MUI는 숫자 값에 4를 곱함 |
| ... | ... | ... |
단일 컴포넌트 내에서 이러한 편차는 작습니다. 하지만 60개의 컴포넌트에 걸쳐 발생하면, 이는 당신의 디자인 시스템이 두 가지 버전으로 존재함을 의미합니다: 디자이너가 구축한 버전과 코드가 구현한 버전입니다.
이것은 프롬프트 엔지니어링 (Prompt Engineering)의 문제가 아닙니다. 더 나은 프롬프트가 AI에게 당신의 시맨틱 토큰 (Semantic Token) 파일을 알려주지는 않습니다. 문제는 구조적이며, 입력값 자체가 잘못되었습니다.
AI 디자인 토큰 생성을 해결하는 방법: 스크린샷이 아닌 Figma API를 읽으세요
이 문제를 해결해 준 통찰은 다음과 같습니다: 디자인 시스템 컴포넌트에는 완전히 다른 두 가지 종류의 결정 사항이 존재한다는 것입니다.
**결정론적 결정 (Deterministic decisions)**은 이 채우기(Fill)에 대한 토큰, 이 크기/두께 조합에 대한 타이포그래피 변형 (Typography variant), 정확한 간격(Spacing) 값과 같이 이미 어딘가에 정확한 정답이 정의되어 있는 결정입니다. 이것들은 판단의 영역이 아닙니다. Figma 파일과 토큰 파일에 존재하는 정답이 있습니다.
**판단적 결정 (Judgment decisions)**은 어떤 변형이 기본값인지, 엣지 케이스 (Edge cases)에서 컴포넌트가 어떻게 동작하는지와 같이 실제 디자인 사고 (Design thinking)를 필요로 합니다. 이것들은 AI의 추론 (Reasoning)으로부터 진정으로 도움을 받을 수 있습니다.
제가 계속 저질렀던 실수는 AI에게 이 두 가지를 한꺼번에 처리하도록 요청하는 것이었습니다. 이 둘을 분리하자 모든 것이 바뀌었습니다.
AI에게 해석할 스크린샷을 주는 대신, Figma의 REST API를 직접 읽기 시작했습니다. API는 정확한 값을 반환합니다. 채우기(Fill)는 정밀한 헥사 코드 (Hex code)로, 타이포그래피는 특정 크기/두께/줄 간격 (Line-height) 조합으로, 간격은 픽셀 측정값으로 반환됩니다. 해석이 필요 없습니다. 정확한 데이터입니다.
수정된 파이프라인 (Pipeline)은 다음과 같습니다:
# 1단계: Figma REST API에서 정확한 값을 읽음 (스크린샷이 아님)
figment scan --node 87YQbb7f33GYUHSOogYGjH:397:23320
...
이제 프롬프트는 더 이상 _"이 디자인을 기반으로 버튼 컴포넌트를 생성해줘."_라고 말하지 않습니다.
이제 프롬프트는 _"배경은 semantic.button.primary이고, 코너 반경(corner radius)은 문자열 리터럴 '8px'이며, 간격(gap)은 tokens.space.2이고, 타이포그래피 변형(typography variant)은 MD_Medium인 버튼 컴포넌트를 생성해줘."_라고 말합니다.
AI는 사실(facts)을 전달받았습니다. 그리고 그 사실로부터 코드를 생성했습니다. 모델이 무언가를 보기 전에 제가 이미 모든 토큰을 해결(resolve)해 두었기 때문에, AI는 토큰 이름을 추측할 필요가 전혀 없었습니다.
생성 방식이 해결하지 못하는 문제: CI에서의 디자인 시스템 드리프트 (Design System Drift)
생성 시점에 값을 정확하게 가져오는 것은 필수적입니다. 하지만 그것만으로는 충분하지 않다는 것을 배웠습니다.
한 달 뒤, 한 개발자가 전혀 관련 없어 보이는 풀 리퀘스트(Pull Request, PR)에서 토큰의 이름을 변경했습니다. 이름 변경 자체는 올바른 작업이었고 필요한 정리 작업이었습니다. 하지만 저를 포함해 아무도 어떤 컴포넌트들이 이전 이름을 사용하고 있었는지 확인하지 않았습니다. 디자인 리뷰 과정에서 디자이너는 프로덕션(production) 환경의 버튼 세 개가 더 이상 Figma 사양(spec)과 일치하지 않는다고 지적했습니다. 극적인 차이는 아니었습니다. 그저 약간 어긋나 있었을 뿐입니다.
이것이 디자인 시스템 드리프트 (design system drift)의 특징입니다. 누군가 주의 깊게 살펴보지 않는 한 눈에 보이지 않습니다.
제가 찾아낸 해결책은 모든 풀 리퀘스트(PR)에서 실행되는 검증 스크립트(verification script)입니다. 이 스크립트는 각 컴포넌트에 대한 실시간 Figma 데이터를 가져오고, 생성 시점에 사용했던 것과 동일한 결정론적 추출기(deterministic extractors)를 다시 실행한 뒤, 그 결과를 현재 컴포넌트 소스 코드와 비교합니다.
# 모든 풀 리퀘스트에서 자동으로 실행됨
npm run verify-figma -- --component Badge --node 87YQbb7f33GYUHSOogYGjH:397:23320
...
Figma 사양에서 벗어난 것이 있다면 스크립트는 실패합니다. 그러면 풀 리퀘스트는 머지(merge)되지 않습니다.
이제 디자인 시스템은 PR을 리뷰하는 사람의 기억력에 의존하지 않습니다. 대신 모든 머지 시점에 지속적으로 검증되는 Figma 파일에 의존하게 됩니다.
프로덕션 환경에 적합한 AI 생성 컴포넌트의 실제 모습
결정론적 사전 해결(deterministic pre-resolution)과 CI 드리프트 탐지(CI drift detection)라는 이 두 가지를 결합하면, 그 결과물은 대부분의 AI 도구가 만들어내는 것과는 구조적으로 다릅니다.
생성된 모든 컴포넌트에는 다음이 포함됩니다:
- ✅ Raw hex 값 없음 — 모든 색상은 시맨틱 토큰 (semantic token)임
- ✅ 정확한 테두리 반경 (border radii) — MUI가 요구하는 위치에 문자열 리터럴 (string literals) 사용
- ✅ 생성 시점의 정확한 Figma 값을 기록하는
.figment.json명세 (spec) 파일 - ✅ 모든 CI 빌드 시 현재 소스에 대해 실행되는 명세 잠금 (spec-lock) 테스트 스위트
- ✅ 의도적인 모든 편차를 서면 근거와 함께 기록하는 오버라이드 (overrides) 파일
이러한 접근 방식을 통해, 원래 예상되었던 120 엔지니어-일 (engineer-days) 대신 영업일 기준 35일 만에 3,077개의 테스트를 거친 60개 이상의 컴포넌트를 출시했습니다. 정리(cleanup) 시간이 거의 제로에 가깝게 줄어든 이유는 사전 해결 (pre-resolution) 단계 덕분이었습니다. 값이 애초에 틀린 적이 없었기에 수정할 것이 아무것도 없었습니다.
왜 제약 조건 우선 (constraint-first) 패턴이 모든 AI 코드 생성에 효과적인가
AI 출력은 기본적으로 근사치입니다. 이를 정확하게 만들려면 AI가 결정할 수 있는 범위를 제한해야 합니다.
저는 이것을 단순한 디자인 시스템의 기술이 아니라 하나의 일반적인 원칙으로 생각하게 되었습니다. AI가 생성하는 코드가 단순히 '그럴듯한' 수준이 아니라 '프로덕션 수준에서 정확해야' 하는 모든 워크플로우는 동일한 구조로부터 이득을 얻습니다.
결정론적인 (deterministic) 부분은 상류 (upstream)에서 해결하십시오. 판단이 필요한 부분은 모델에 위임하십시오. 파일을 작성하기 전에 출력물에서 위반 사항을 스캔하십시오. 모든 풀 리퀘스트 (pull request)에서 신뢰할 수 있는 단일 출처 (source of truth)와 대조하여 검증하십시오.
대부분의 팀은 제약 조건을 설정하는 것이 오버헤드(overhead)처럼 보이기 때문에 이를 건너뜁니다. 그러고는 왜 AI가 생성한 모든 컴포넌트가 사용 가능해지기 전에 수동 정리 과정을 거쳐야 하는지 의아해합니다.
그 정리 작업은 AI에게 제대로 수행하도록 설계되지 않은 결정을 내리라고 요구한 것에 대한 비용입니다. 제가 AI에게 그런 질문들을 던지는 것을 멈추자, AI는 더 이상 틀린 답을 내놓지 않았습니다.
작성자: Amrutha Kollu, 소프트웨어 엔지니어.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기