이 글은 누구를 위한 것인가
- Figma Variables를 써봤지만 아직 기본 색상/크기 정도만 활용하는 디자이너
- 복잡한 조건부 스타일링을 Figma 안에서 처리하고 싶은 디자인 시스템 담당자
- 개발 팀에 넘기기 전 디자인 단계에서 더 많은 로직을 표현하고 싶은 분
들어가며
Figma Variables가 처음 나왔을 때 많은 팀이 이렇게 사용했다. 색상 값을 변수로 만들고, 라이트/다크 모드를 컬렉션으로 분리하고, 개발 팀에 토큰을 전달하는 용도. 유용했지만, 기존 CSS 변수나 디자인 토큰 JSON 파일을 Figma 안으로 옮긴 것에 가까웠다.
2025년 말 출시된 Expression Tokens는 이 그림을 완전히 바꿨다. 단순한 값이 아닌 수식과 조건 로직을 변수에 담을 수 있다. 컨테이너 크기에 비례하는 폰트 크기, 상태에 따라 자동으로 변하는 색상 계산, 여러 조건을 조합한 복합 스타일 — 이것들을 Figma 안에서 직접 정의할 수 있게 됐다.
이 글에서는 Expression Tokens의 실전 활용법을 구체적인 예시와 함께 다룬다.
1. Figma Variables 복습: 지금까지 할 수 있던 것
Expression Tokens를 이해하려면 기존 Variables의 한계를 먼저 짚어야 한다.
기존 Variables로 할 수 있는 것
컬렉션: Brand Colors
- primary: #2563EB
- primary-hover: #1D4ED8
- primary-disabled: #93C5FD
컬렉션: Spacing
- sm: 8
- md: 16
- lg: 24
이 구조로 라이트/다크 모드 전환, 브랜드 테마 변경은 잘 된다.
기존 Variables의 한계
문제 1: primary-hover가 primary보다 항상 20% 어두워야 한다는 규칙이 있어도, 매번 수동으로 계산해서 값을 넣어야 한다. primary 색상을 바꾸면 primary-hover도 손으로 다시 계산해야 한다.
문제 2: "컨테이너가 600px 이상일 때는 heading-lg, 미만일 때는 heading-md를 써라"는 조건을 Variables로 표현할 수 없다. 개발 팀에 말로 전달하거나 주석으로 남길 수밖에 없었다.
Expression Tokens가 이 두 문제를 해결한다.
2. Expression Tokens 기초: 수식으로 값 계산하기
Expression Tokens는 변수 값으로 다른 변수를 참조하거나 수식을 사용할 수 있게 한다.
색상 관계 자동 계산
// 기존 방식: 수동으로 각각 값 입력
primary: #2563EB
primary-hover: #1D4ED8 (직접 계산)
primary-active: #1E40AF (직접 계산)
primary-disabled: #BFDBFE (직접 계산)
// Expression Tokens 방식: 수식으로 관계 정의
primary: #2563EB
primary-hover: darken({primary}, 10%) // primary의 10% 어두운 버전
primary-active: darken({primary}, 20%) // primary의 20% 어두운 버전
primary-disabled: lighten({primary}, 40%) // primary의 40% 밝은 버전
이제 primary 값 하나만 바꾸면 hover, active, disabled 상태가 전부 자동으로 업데이트된다. 색상 팔레트를 교체할 때 실수로 hover 상태를 빠뜨리는 일이 없어진다.
스케일 기반 타이포그래피 자동 계산
// 베이스 크기와 스케일 비율만 정의
base-font-size: 16
type-scale-ratio: 1.25
// 나머지는 수식으로 자동 계산
font-sm: {base-font-size} / {type-scale-ratio} // 12.8
font-md: {base-font-size} // 16
font-lg: {base-font-size} * {type-scale-ratio} // 20
font-xl: {base-font-size} * pow({type-scale-ratio}, 2) // 25
font-2xl: {base-font-size} * pow({type-scale-ratio}, 3) // 31.25
type-scale-ratio를 1.25에서 1.333으로 바꾸면 타이포그래피 스케일 전체가 한번에 재계산된다.
3. 조건 로직: if/else를 변수에
Expression Tokens의 가장 강력한 기능은 조건 표현식이다.
상태 기반 색상 조건
버튼 배경색이 활성화 상태, 비활성화 상태, 로딩 상태에 따라 달라져야 한다면:
// if(조건, 참일 때 값, 거짓일 때 값) 형식
button-bg: if(
{isDisabled},
{color-disabled},
if({isLoading}, {color-loading}, {color-primary})
)
이 변수를 쓰는 컴포넌트는 isDisabled와 isLoading 불리언 변수만 토글하면 배경색이 자동으로 적절한 값으로 변한다. 디자이너가 상태별로 레이어를 복사/붙여넣기 할 필요가 없다.
사이즈 기반 조건: 반응형 토큰
// 컨테이너 너비에 따라 달라지는 패딩
card-padding: if(
{containerWidth} >= 600,
{spacing-lg},
if({containerWidth} >= 400, {spacing-md}, {spacing-sm})
)
// 컨테이너 너비에 따라 달라지는 폰트 크기
card-title-size: if(
{containerWidth} >= 600,
{font-xl},
{font-lg}
)
이 토큰들이 적용된 카드 컴포넌트는 놓이는 컨테이너 크기에 따라 자동으로 다른 패딩과 폰트 크기를 갖는다. Container Query의 개념을 Figma 안으로 가져온 것이다.
4. 실전 예시: 동적 카드 컴포넌트
위의 개념을 실제 카드 컴포넌트 설계에 적용해보자.
토큰 구조 설계
컬렉션: Card Tokens
// 크기 관련
card-padding: if({containerWidth} >= 500, 24, 16)
card-gap: if({containerWidth} >= 500, 16, 12)
card-image-height: if({containerWidth} >= 500, 200, 140)
// 타이포그래피
card-title-size: if({containerWidth} >= 500, {font-lg}, {font-md})
card-title-weight: if({isFeatured}, 700, 500)
card-desc-size: {font-sm}
// 색상
card-bg: if({isHighlighted}, {color-highlight-bg}, {color-surface})
card-border: if({isSelected}, 2px solid {color-primary}, 1px solid {color-border})
card-shadow: if({isHovered}, {shadow-md}, {shadow-sm})
컴포넌트 변수 연결
Figma Variables 패널에서 이 토큰들을 컴포넌트의 각 요소에 연결한다.
카드 프레임
└─ padding: {card-padding}
└─ background: {card-bg}
└─ border: {card-border}
└─ effect: {card-shadow}
제목 텍스트
└─ font-size: {card-title-size}
└─ font-weight: {card-title-weight}
이미지 프레임
└─ height: {card-image-height}
이제 containerWidth, isFeatured, isHighlighted, isSelected, isHovered 변수를 토글하면 카드의 모든 스타일이 자동으로 업데이트된다. 상태별 복사본을 만들지 않아도 하나의 컴포넌트로 모든 상태를 표현한다.
5. 개발 팀과의 협업: 토큰을 코드로 내보내기
Expression Tokens로 만든 디자인 시스템의 진짜 가치는 개발 팀에 전달될 때 발현된다.
Token Studio와의 연동
Token Studio 플러그인을 사용하면 Figma Variables를 W3C Design Token 표준 형식의 JSON으로 내보낼 수 있다.
{
"card": {
"padding": {
"$type": "dimension",
"$value": "{spacing.md}",
"$extensions": {
"figma:expression": "if({containerWidth} >= 500, 24, 16)"
}
},
"bg": {
"$type": "color",
"$value": "{color.surface}",
"$extensions": {
"figma:expression": "if({isHighlighted}, {color.highlight.bg}, {color.surface})"
}
}
}
}
수식 정보가 $extensions에 포함돼 개발 팀이 동일한 조건 로직을 CSS나 컴포넌트 코드로 구현할 때 참고할 수 있다.
CSS Custom Properties로 변환
/* 토큰 JSON에서 자동 생성된 CSS */
.card {
--card-padding: clamp(16px, calc(16px + (24 - 16) * (100% - 400px) / 100), 24px);
padding: var(--card-padding);
}
/* 조건 로직은 CSS Container Queries로 변환 */
@container (min-width: 500px) {
.card-title {
font-size: var(--font-lg);
}
}
@container (max-width: 499px) {
.card-title {
font-size: var(--font-md);
}
}
6. Expression Tokens 도입 시 주의할 점
강력한 기능이지만 잘못 쓰면 복잡도만 높아진다.
주의 1: 수식이 너무 복잡해지면 안 된다
3단계 이상의 중첩 조건은 디자이너도, 개발자도 이해하기 어렵다. 복잡한 수식은 별도 토큰으로 쪼개는 것이 낫다.
// 나쁜 예: 너무 복잡한 수식 하나
button-color: if({isDisabled}, gray, if({isLoading}, blue, if({isDanger}, red, if({isPrimary}, navy, black))))
// 좋은 예: 의미 있는 중간 토큰으로 분리
button-base-color: if({isDanger}, red, if({isPrimary}, navy, black))
button-color: if({isDisabled}, gray, if({isLoading}, blue, {button-base-color}))
주의 2: 토큰 이름 규칙을 팀이 합의해야 한다
Expression Tokens로 만든 동적 토큰과 정적 토큰이 섞이면 혼란스럽다. dynamic- 접두사를 붙이거나, 별도 컬렉션으로 분리하는 규칙을 미리 정해야 한다.
주의 3: 개발 팀에게 맥락을 전달하라
Expression Tokens의 수식은 Figma 안에서는 자동으로 계산되지만, 개발 팀이 이를 코드로 옮길 때는 의도를 이해해야 한다. 토큰에 설명(description)을 달고, 어떤 조건을 표현하는지 명시하자.
맺으며
Figma Variables의 Expression Tokens는 디자인 시스템을 "값의 집합"에서 "규칙의 집합"으로 진화시킨다. 색상 하나를 바꿨을 때 연관된 모든 상태가 자동으로 업데이트되고, 컴포넌트의 조건부 동작이 Figma 안에서 시각적으로 확인된다.
처음부터 모든 것을 Expression Tokens로 바꿀 필요는 없다. 가장 반복적으로 수작업이 필요했던 부분, 예를 들어 hover/active 상태 색상 계산이나 반응형 스페이싱부터 시작해보자. 작은 변화가 팀 전체의 워크플로를 얼마나 바꾸는지 직접 경험하면, 어디까지 확장할지 자연스럽게 보이게 된다.