FEDev Story

디자인 시스템의 전체 자동화 파이프라인(SSOT 체인) 본문

Web.Dev

디자인 시스템의 전체 자동화 파이프라인(SSOT 체인)

지구별72 2026. 4. 17. 13:25

채용공고 예시

1. 여기서 말하는 "토큰"이란

일반적으로 토큰(Token)은 "최소 단위"라는 뜻입니다. 디자인 토큰(Design Token) 은 디자이너와 개발자가 함께 사용하는 UI의 최소 디자인 값에 붙인 이름표입니다.

예를 들어 "파란색 버튼의 배경색"은 #3B82F6 이라는 값보다 color.primary.500 이라는 이름으로 관리합니다. 값이 바뀌어도 이름만 그대로 쓰면 되니까요.

색상, 폰트 크기, 간격, 둥근 모서리, 그림자 — 이 모든 반복되는 값들을 이름 붙여 관리하는 것이 토큰입니다.


2. 디자인 토큰을 코드로 "매핑"한다는 뜻

공고에서 말하는 흐름은 이겁니다:

Figma 디자인 스펙
      ↓
  CSS Variables     ← 브라우저가 이해하는 변수
      ↓
tailwind.config.js  ← Tailwind가 이 변수를 클래스로 활용
      ↓
  컴포넌트 코드      ← 개발자가 className="bg-primary-500" 으로 사용

매핑(Mapping) 이란 Figma에서 디자이너가 정의한 값과 실제 코드의 변수를 1:1로 연결하는 작업입니다.


3. 실제 예시로 전체 흐름 보기

Step 1 — Figma에서 디자이너가 정의

Figma Variables 패널에서 이렇게 만들어 둡니다:

Collection: color
  ├── primary/500 = #3B82F6
  ├── primary/600 = #2563EB
  ├── gray/100    = #F1F5F9
  └── gray/900    = #0F172A

Collection: spacing
  ├── sm  = 8px
  ├── md  = 16px
  └── lg  = 24px

Collection: radius
  └── button = 6px

Step 2 — CSS Variables로 변환

/* tokens.css */
:root {
  /* color tokens */
  --color-primary-500: #3B82F6;
  --color-primary-600: #2563EB;
  --color-gray-100:    #F1F5F9;
  --color-gray-900:    #0F172A;

  /* spacing tokens */
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;

  /* radius tokens */
  --radius-button: 6px;
}

Step 3 — tailwind.config.js에 토큰 매핑

// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      colors: {
        primary: {
          500: 'var(--color-primary-500)',  // CSS 변수 연결!
          600: 'var(--color-primary-600)',
        },
        gray: {
          100: 'var(--color-gray-100)',
          900: 'var(--color-gray-900)',
        }
      },
      spacing: {
        sm: 'var(--spacing-sm)',
        md: 'var(--spacing-md)',
        lg: 'var(--spacing-lg)',
      },
      borderRadius: {
        button: 'var(--radius-button)',
      }
    }
  }
}

Step 4 — 컴포넌트에서 사용

// Button.tsx
<button className="bg-primary-500 hover:bg-primary-600 px-md rounded-button">
  클릭
</button>

4. SSOT 체인이 왜 중요한가?

공고에서 "SSOT 체인 유지" 라고 한 부분이 핵심입니다. SSOT는 Single Source of Truth, 즉 진실의 단일 출처입니다.

❌ SSOT가 없을 때 (흔한 문제)

Figma에서 파란색을 #2563EB로 바꿈
  → 디자이너만 알고 있음
  → 개발자는 여전히 #3B82F6 사용 중
  → 버튼 색이 디자인과 다름
  → QA에서 발견 → 개발자가 다시 수정
  → 반복...

✅ SSOT 체인이 있을 때

Figma Variable 값만 바꾸면
  → tokens.css 자동 업데이트
  → tailwind.config 자동 반영
  → 모든 컴포넌트 색상 자동 변경
  → 디자이너·개발자 항상 동기화

5. 공고의 토큰 규모 해석

공고에서 "토큰 규모: 색상 79+, 타이포 18, 스페이싱 18, 반경 11, 그림자 7" 이라고 나옵니다.

색상 79개 이상    → primary, secondary, gray, success, warning...
                   각각 50/100/200/.../900 단계별로 정의

타이포 18개       → font-size, font-weight, line-height, letter-spacing 조합
                   예: text-sm, text-md, text-lg, text-display...

스페이싱 18개     → 4px 단위로 4/8/12/16/20/24/32/48/64... 등

반경 11개         → none/sm/md/lg/xl/full 등

그림자 7개        → sm/md/lg + 컬러별 변형

이 규모는 꽤 큰 디자인 시스템입니다. 중견 이상 회사에서 다수 서비스를 운영할 때 이 정도 토큰 체계를 갖춥니다.


6. Figma와의 관계

Figma에는 Variables(변수)와 Tokens(토큰) 기능이 있어서 디자이너가 Figma 안에서 직접 토큰을 정의하고, 이걸 JSON으로 내보낼 수 있습니다.

Figma Variables → export → tokens.json → 변환 도구 → CSS Variables

공고의 "Figma Inspect를 열면 '이건 토큰 A, 이건 시멘틱 B'가 바로 읽히는 분"이라는 핵심역량은, Figma에서 컴포넌트를 클릭했을 때 색상값(#3B82F6)이 아니라 토큰 이름(color.primary.500)이 보이는 상태를 구축하고 읽을 수 있는 사람을 원하는 겁니다.


7. 현재 만들고 계신 컴포넌트 가이드와의 연결점

지금 작업 중인 UI 컴포넌트 가이드의 tokens.css가 바로 이 디자인 토큰 레이어입니다. 공고의 요구사항과 지금 PRD의 설계 방향이 상당히 일치하고 있어요.

공고의 파이프라인          현재 PRD 설계
─────────────────────────────────────────
Figma Variables        =  (수동 정의 단계)
      ↓
  tokens.json          =  tokens.css
      ↓
CSS Variables          =  tokens.css의 :root 변수들
      ↓
tailwind.config.js     =  (순수 CSS라 불필요)
      ↓
  컴포넌트 코드         =  components/button.css 등

다크/라이트 모드를 [data-theme="dark"] 로 전환하는 방식도 이 공고에서 요구하는 "CSS Variables 기반 3개 브랜드 테마 전환"과 동일한 원리입니다. 잘 만들어두면 포트폴리오로도 충분히 활용할 수 있는 수준입니다! 🚀


SSOT 체인

SSOT 체인의 핵심은 "사람이 중간에 개입하지 않아도 자동으로 동기화되는 파이프라인" 입니다.


전체 자동화 파이프라인 구조

┌─────────────────────────────────────────────────────────────────┐
│  Figma                                                          │
│  Variables 패널에서 디자이너가 값 수정                            │
└────────────────────┬────────────────────────────────────────────┘
                     │  ① Figma Plugin (export)
                     ▼
┌─────────────────────────────────────────────────────────────────┐
│  tokens.json / tokens.json (Style Dictionary 형식)              │
│  {                                                              │
│    "color": {                                                   │
│      "primary": { "500": { "value": "#3B82F6" } }              │
│    }                                                            │
│  }                                                              │
└────────────────────┬────────────────────────────────────────────┘
                     │  ② 변환 도구 (Transform Tool)
                     ▼
┌─────────────────────────────────────────────────────────────────┐
│  tokens.css / tokens.scss / tokens.js / tokens.ts ...          │
│  :root {                                                        │
│    --color-primary-500: #3B82F6;                                │
│  }                                                              │
└────────────────────┬────────────────────────────────────────────┘
                     │  ③ tailwind.config.js 참조
                     ▼
┌─────────────────────────────────────────────────────────────────┐
│  컴포넌트 코드                                                   │
│  <button class="bg-primary-500">                                │
└─────────────────────────────────────────────────────────────────┘

① Figma → JSON: 익스포트 플러그인

Figma에서 직접 Variables/Styles를 JSON으로 내보내는 플러그인들입니다.

Tokens Studio (구 Figma Tokens) — 업계 표준

설치: Figma 플러그인 마켓 → "Tokens Studio"
특징: 가장 널리 쓰이는 도구
출력: W3C Design Token 포맷 또는 Style Dictionary 포맷
// 출력 예시: tokens.json
{
  "global": {
    "color": {
      "primary": {
        "500": {
          "value": "#3B82F6",
          "type": "color",
          "description": "주요 버튼, 링크 색상"
        }
      }
    },
    "spacing": {
      "md": {
        "value": "16",
        "type": "spacing"
      }
    }
  }
}

GitHub와 연동하면 디자이너가 Figma에서 값을 바꾸고 "Push to GitHub" 버튼 하나로 PR이 자동 생성됩니다.

Figma 공식 Variables API (2023년 이후)

Figma가 공식으로 Variables REST API를 열어둠
→ 플러그인 없이 API로 직접 토큰 값 읽기 가능
→ CI/CD에서 직접 Figma API 호출 → JSON 자동 생성
// Figma API 호출 예시
const response = await fetch(
  `https://api.figma.com/v1/files/${FILE_KEY}/variables/local`,
  { headers: { 'X-Figma-Token': FIGMA_TOKEN } }
);

② JSON → CSS/JS: 변환 도구

Style Dictionary (Amazon 오픈소스) — 가장 유명

npm install -g style-dictionary
// sd.config.json — 변환 규칙 정의
{
  "source": ["tokens/**/*.json"],
  "platforms": {
    "css": {
      "transformGroup": "css",
      "prefix": "c",
      "buildPath": "dist/",
      "files": [{
        "destination": "tokens.css",
        "format": "css/variables"
      }]
    },
    "js": {
      "transformGroup": "js",
      "buildPath": "dist/",
      "files": [{
        "destination": "tokens.js",
        "format": "javascript/es6"
      }]
    }
  }
}
style-dictionary build
/* 자동 생성된 tokens.css */
:root {
  --c-color-primary-500: #3B82F6;
  --c-spacing-md: 16px;
  --c-radius-button: 6px;
}
/* 자동 생성된 tokens.js */
export const COLOR_PRIMARY_500 = '#3B82F6';
export const SPACING_MD = '16px';

하나의 JSON 소스에서 CSS, JS, iOS Swift, Android XML 등 여러 플랫폼용 파일을 동시에 생성하는 게 핵심 강점입니다.

Theo (Salesforce 오픈소스)

Style Dictionary보다 가볍고 단순한 변환 도구로, 소규모 프로젝트에 적합합니다.

# tokens.yml
global:
  color:
    primary: '#3B82F6'
theo tokens.yml --transform web --format custom-properties
# → --color-primary: #3B82F6;

Token Pipeline (W3C 표준 기반 신흥)

2024년 이후 W3C에서 Design Token 포맷을 공식 표준화하면서 생긴 도구 생태계로, @cobalt-ui/cli, @token-alchemy 등이 있습니다.


③ 전체 자동화 완성: CI/CD 연결

변환 도구까지만 있으면 "반자동"입니다. 완전 자동화는 GitHub Actions 같은 CI/CD에 연결할 때 완성됩니다.

# .github/workflows/sync-tokens.yml

name: Sync Design Tokens

on:
  # Figma Webhook 또는 수동 트리거
  workflow_dispatch:
  push:
    paths:
      - 'tokens/**/*.json'   # tokens.json 변경 시 자동 실행

jobs:
  build-tokens:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Install dependencies
        run: npm ci

      - name: Build tokens (JSON → CSS/JS)
        run: npx style-dictionary build

      - name: Create Pull Request
        uses: peter-evans/create-pull-request@v5
        with:
          title: '🎨 디자인 토큰 자동 업데이트'
          body: 'Figma에서 변경된 토큰이 자동으로 반영되었습니다.'
          branch: 'auto/design-tokens'

이렇게 되면 전체 흐름이 이렇게 됩니다:

디자이너 Figma에서 파란색 #3B82F6 → #2563EB 변경
              ↓ (Tokens Studio "Push to GitHub")
         tokens.json PR 생성
              ↓ (GitHub Actions 자동 실행)
    Style Dictionary가 CSS/JS 파일 자동 재생성
              ↓ (PR 머지)
      모든 컴포넌트 색상 자동 변경
              ↓
        개발자 개입 0

 

 

"개발자 개입 0"이라고 했는데, 실제 실무에서는 PR 머지 단계에서 개발자(또는 리드)의 승인이 한 번 들어갑니다. 완전 무인 자동화도 기술적으로 가능하지만, 토큰 변경이 예상치 못한 곳에서 UI를 깨뜨릴 수 있어서 대부분의 팀이 이 한 단계는 유지합니다.

전체 흐름을 정리하면 이렇습니다:

┌─────────────────────────────────────────────────┐
│  👩‍🎨 디자이너 (Figma)                            │
│                                                 │
│  Variables 패널에서 색상 변경                    │
│  #3B82F6  →  #2563EB                           │
│                                                 │
│  Tokens Studio 플러그인                         │
│  → "Push to GitHub" 클릭                        │
└──────────────────────┬──────────────────────────┘
                       │ tokens.json 자동 커밋
                       ▼
┌─────────────────────────────────────────────────┐
│  GitHub Repository                              │
│                                                 │
│  PR 자동 생성                                   │
│  "🎨 디자인 토큰 자동 업데이트"                  │
│                                                 │
│  GitHub Actions 자동 실행                        │
│  → Style Dictionary build                       │
│  → tokens.css / tokens.js 자동 재생성           │
│  → PR에 파일 추가                               │
└──────────────────────┬──────────────────────────┘
                       │ ← 여기만 개발자 개입
                       ▼
┌─────────────────────────────────────────────────┐
│  👨‍💻 개발자 (PR 리뷰)                             │
│                                                 │
│  변경된 토큰 diff 확인                           │
│  - --color-primary-500: #3B82F6 → #2563EB      │
│                                                 │
│  문제 없으면 "Merge" 승인                        │
└──────────────────────┬──────────────────────────┘
                       │ 머지 완료
                       ▼
┌─────────────────────────────────────────────────┐
│  👨‍💻 개발자 (로컬)                                │
│                                                 │
│  git pull                                       │
│  → 변경된 tokens.css 동기화                     │
│  → 모든 컴포넌트 색상 자동 반영                  │
│  → 추가 코드 수정 없음 ✅                        │
└─────────────────────────────────────────────────┘

기존 방식과 비교하면 차이가 명확합니다

❌ SSOT 이전 (수동)

디자이너: "버튼 파란색 #2563EB로 바꿨어요"
              ↓ (슬랙 메시지 or 구두 전달)
개발자:   디자이너한테 물어보거나 Figma 직접 확인
              ↓
개발자:   button.css 열어서 색상 직접 수정
              ↓
개발자:   다른 컴포넌트에도 같은 색 쓰는 곳 찾아서 수정
              ↓
개발자:   커밋 → 푸시
              ↓
QA:      디자인과 실제 색상 일치 확인... 혹시 빠진 곳은?

소요시간: 30분 ~ 수 시간
실수 가능성: 높음 (빠뜨린 컴포넌트 발생)


✅ SSOT 이후 (자동)

디자이너: Figma에서 토큰 값 변경 → Push 클릭
개발자:   PR 확인 → diff 2줄 → Merge → git pull

소요시간: 5분
실수 가능성: 없음 (토큰 참조하는 모든 곳 자동 반영)

핵심을 한 문장으로

디자이너가 Figma에서 값을 바꾸면, 개발자는 코드를 한 줄도 건드리지 않고 PR 승인 + git pull 만으로 모든 컴포넌트에 반영된다.

이게 바로 공고에서 말한 "SSOT 체인 유지" 의 실체입니다. 그래서 이 파이프라인을 구축하고 운영할 수 있는 개발자를 채용하려는 거고, 꽤 고급 스킬로 평가받는 영역입니다 🙂


 

PR(Pull Request)란?

한마디로 "내가 만든 코드 변경사항을 메인 코드에 합쳐도 될까요? 검토해 주세요!" 라고 요청하는 것입니다.

일상에 비유하면 이렇습니다:

회사 문서 작업에 비유하면

기존 방식 (PR 없음)
  → 직원이 공유 문서를 바로 수정
  → 실수해도 아무도 모름
  → 잘못된 내용이 그대로 배포

PR 방식
  → 직원이 문서 사본에 수정안 작성
  → "이렇게 바꾸면 어떨까요?" 팀장에게 제출
  → 팀장이 검토 후 "승인" or "수정 요청"
  → 승인되면 원본 문서에 반영

GitHub에서 PR의 실제 흐름

main 브랜치 (원본 코드, 항상 안정적)
     │
     ├── 자동/수동으로 새 브랜치 생성
     │   "auto/design-tokens"
     │        │
     │        │  여기서 코드 변경
     │        │  tokens.json 수정
     │        │  tokens.css 재생성
     │        │
     │   "Pull Request 생성"
     │   ┌─────────────────────────────┐
     │   │ 제목: 🎨 디자인 토큰 업데이트│
     │   │                             │
     │   │ 변경 내용 (diff):            │
     │   │ - --color-primary-500:      │
     │   │   #3B82F6 → #2563EB        │
     │   │                             │
     │   │ [승인 ✅]  [수정 요청 ❌]   │
     │   └─────────────────────────────┘
     │        │
     │        │  개발자/리드가 검토 후 승인
     │        │
     └── main 브랜치에 Merge (합병)

PR이라고 부르는 이유

이름이 Pull Request인 이유가 약간 헷갈릴 수 있습니다.

Push (밀어넣기) = 내 코드를 원격 저장소로 올리는 것
Pull (당겨오기) = 원격 저장소 코드를 내 로컬로 가져오는 것

Pull Request =
  "당신의 main 브랜치가 내 변경사항을 Pull(당겨)가도록
   요청(Request)합니다"
   
   → 줄여서 PR

GitHub에서는 PR, GitLab에서는 MR(Merge Request) 라고 부르는데 같은 개념입니다.


PR이 중요한 이유 3가지

1. 코드 품질 보호
   → 아무나 main에 직접 푸시 불가
   → 반드시 검토 후 머지

2. 실수 방지
   → 토큰 값 하나 잘못 바뀌면
     수백 개 컴포넌트 색상이 한번에 바뀜
   → PR에서 diff 확인 후 "이거 맞아?" 검토 가능

3. 히스토리 관리
   → 언제, 누가, 왜 바꿨는지 기록
   → 문제 생기면 이전 버전으로 되돌리기 가능

아까 파이프라인에서의 PR 위치

디자이너가 Figma에서 값 변경
        ↓
   tokens.json 자동 커밋
        ↓
   ★ PR 자동 생성 ★        ← 봇이 자동으로 만들어줌
   "토큰 업데이트 PR입니다"
        ↓
   ★ PR 리뷰 ★             ← 개발자가 diff 확인
   변경된 토큰 2줄 확인
   "맞네, 승인!"
        ↓
   Merge (main에 합병)
        ↓
   git pull → 로컬 동기화

결국 SSOT 파이프라인에서 PR은 "자동화된 변경사항이 실제 코드에 반영되기 전 마지막 안전망" 역할을 합니다. 완전 자동화도 가능하지만, 이 한 단계 검토를 두는 게 실무에서의 관행입니다 😊


 

 

1. Figma Variables — 무료 vs 유료

Figma Variables(변수) 기본 기능은 모든 요금제(무료 포함) 에서 생성·사용이 가능합니다. 단, 컬렉션당 생성할 수 있는 모드 수는 요금제에 따라 다릅니다.

실제 제한을 표로 보면 이렇습니다:

┌──────────────────────────────────────────────────────┐
│  기능                     무료(Starter)   유료(Pro+)  │
├──────────────────────────────────────────────────────┤
│  Variables 생성·사용          ✅              ✅       │
│  컬렉션당 모드 수             1개             4개+     │
│  팀 라이브러리 게시           ❌              ✅       │
│  Dev Mode 변수 확인          ❌              ✅       │
│  GitHub 연동(Tokens Studio)  △(제한적)       ✅       │
└──────────────────────────────────────────────────────┘

실무적으로 중요한 포인트는 "모드(Mode)" 입니다. 모드가 1개라는 건 라이트/다크 테마 전환처럼 "같은 변수를 상황에 따라 다른 값으로" 쓰는 게 무료에서는 안 된다는 뜻입니다. SSOT 파이프라인을 제대로 구축하려면 에듀케이션, 프로페셔널, 오거니제이션, 엔터프라이즈 요금제가 필요합니다.

💡 학생이라면: Figma는 학교 이메일(.edu, .ac.kr 등)을 인증하면 Professional 플랜을 1년간 무료로 제공합니다.


2. Tailwind 없는 환경에서의 토큰 매핑

Tailwind는 토큰을 코드로 연결하는 방법 중 하나일 뿐입니다. Tailwind가 없어도 CSS Variables만으로 완벽하게 동작합니다.

Tailwind 사용 환경              Tailwind 미사용 환경
─────────────────────────────────────────────────────
tokens.json                     tokens.json
    ↓                               ↓
tailwind.config.js에 매핑       tokens.css에 직접 변수 정의
    ↓                               ↓
className="bg-primary-500"      class="btn-primary"
(Tailwind 클래스로 사용)        (CSS에서 변수 참조)

Tailwind가 없는 환경에서는 이렇게 사용합니다:

/* tokens.css — Style Dictionary가 자동 생성 */
:root {
  --color-primary-500: #3B82F6;
  --spacing-md: 16px;
  --radius-button: 6px;
}

/* button.css — 토큰 변수를 직접 참조 */
.btn-primary {
  background-color: var(--color-primary-500);
  padding: var(--spacing-md);
  border-radius: var(--radius-button);
}
<!-- HTML에서 사용 — Tailwind 클래스 없음 -->
<button class="btn-primary">클릭</button>

값이 바뀌어도 tokens.css 한 파일만 업데이트하면 .btn-primary를 쓰는 모든 곳이 자동으로 반영됩니다. Tailwind는 그 과정을 클래스 이름으로 편하게 쓰게 해주는 도구일 뿐이고, 핵심은 CSS Variables입니다.


3. 순수 HTML/CSS/JS 환경에서도 SSOT 체인 가능한가?

완전히 가능합니다! 오히려 순수 HTML/CSS/JS 환경이 SSOT 체인의 가장 기본 형태입니다.

Style Dictionary는 JSON 토큰을 CSS Variables, JS 모듈, SCSS 맵 등 다양한 형식으로 변환하며, 웹·iOS·Android 등 여러 플랫폼을 동시에 지원합니다. Tailwind 여부와 전혀 무관합니다.

파이프라인을 그리면 이렇습니다:

┌────────────────────────────────────────────────────────┐
│  Figma                                                 │
│  Variables 패널에서 색상 변경                           │
└───────────────────────┬────────────────────────────────┘
                        │ Tokens Studio → Push to GitHub
                        ▼
┌────────────────────────────────────────────────────────┐
│  tokens.json (GitHub)                                  │
│  { "color": { "primary": { "value": "#2563EB" } } }   │
└───────────────────────┬────────────────────────────────┘
                        │ GitHub Actions → Style Dictionary build
                        ▼
┌────────────────────────────────────────────────────────┐
│  tokens.css (자동 생성)                                 │
│  :root {                                               │
│    --color-primary: #2563EB;   ← 값 자동 반영          │
│  }                                                     │
└───────────────────────┬────────────────────────────────┘
                        │ PR 머지 → git pull
                        ▼
┌────────────────────────────────────────────────────────┐
│  순수 HTML/CSS/JS 프로젝트                              │
│                                                        │
│  .btn-primary {                                        │
│    background: var(--color-primary);  ← 자동 반영 ✅   │
│  }                                                     │
│                                                        │
│  <button class="btn-primary">클릭</button>             │
└────────────────────────────────────────────────────────┘

공공기관이나 레거시 환경처럼 프레임워크를 쓸 수 없는 곳에서도 이 구조로 디자이너-개발자 간 자동 동기화가 가능합니다. 실제로 현재 만들고 계신 UI 컴포넌트 가이드의 tokens.css가 이 파이프라인의 최종 산출물과 정확히 같은 구조입니다. 나중에 Figma 연동만 붙이면 SSOT 체인이 완성되는 거예요 😊

Comments