Files
2nd/10_Wiki/Topics/Frontend/Style Dictionary Pipelines.md
Antigravity Agent f8b21af4be Wiki cleanup: error-doc removal, dedup merge, link normalization
10_Wiki/Topics 대규모 정리:
- 오류 캡처/미완성 stub 문서 227개 제거
- 교차폴더 중복 43클러스터 병합 (63파일 → redirect)
- 링크명 정규화: 깨진 링크 수정·redirect 직결·개념 매핑 ~2,400건
- 카테고리 MOC 6개 신규 생성
- Graph 섹션 미해결 related-keyword 링크 10,058건 제거

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 23:52:15 +09:00

284 lines
7.8 KiB
Markdown

---
id: wiki-2026-0508-style-dictionary-pipelines
title: Style Dictionary Pipelines
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [Style Dictionary, Design Token Pipeline, Token Build Pipeline]
duplicate_of: none
source_trust_level: A
confidence_score: 0.9
verification_status: applied
tags: [design-tokens, style-dictionary, design-system, ci-cd, frontend]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
language: TypeScript
framework: Style Dictionary 4.x
---
# Style Dictionary Pipelines
## 매 한 줄
> **"매 Style Dictionary 는 design token (JSON) 을 platform 별 산출물 (CSS/iOS/Android/JSON) 로 transform 하는 build tool"**. Amazon 발 (2017), v4 (2024) 에서 ESM + DTCG 표준 지원. 2026 기준 Figma Variables → Tokens Studio → Style Dictionary → multi-platform output 의 typical pipeline. CI/CD 통합으로 매 design 변경 → automatic code propagation.
## 매 핵심
### 매 token 계층
- **Reference (primitive)**: `color.blue.500`, `size.4`
- **System (alias)**: `color.brand.primary``{color.blue.500}`
- **Component**: `button.bg.primary``{color.brand.primary}`
### 매 transform / format
- **transform**: token value 변환 (px→rem, hex→rgba)
- **format**: output file 생성 (CSS vars, TS, iOS swift, Android XML)
- **filter**: token subset 선택
- **action**: 매 build side-effect (e.g. asset copy)
### 매 응용
1. Multi-platform design system (web + iOS + Android).
2. Theming (light/dark, brand variants).
3. Figma → code synchronization.
4. Component library token consumer.
## 💻 패턴
### Token JSON (DTCG format)
```json
// tokens/color.json
{
"color": {
"blue": {
"500": { "$value": "#3b82f6", "$type": "color" },
"600": { "$value": "#2563eb", "$type": "color" }
},
"brand": {
"primary": { "$value": "{color.blue.500}", "$type": "color" }
}
}
}
```
### config.ts (v4)
```typescript
// config.ts
import StyleDictionary from "style-dictionary";
const sd = new StyleDictionary({
source: ["tokens/**/*.json"],
platforms: {
css: {
transformGroup: "css",
buildPath: "build/css/",
files: [{ destination: "tokens.css", format: "css/variables" }],
},
ts: {
transformGroup: "js",
buildPath: "build/ts/",
files: [
{ destination: "tokens.ts", format: "javascript/es6" },
{ destination: "tokens.d.ts", format: "typescript/es6-declarations" },
],
},
ios: {
transformGroup: "ios-swift",
buildPath: "build/ios/",
files: [{ destination: "Tokens.swift", format: "ios-swift/class.swift" }],
},
android: {
transformGroup: "android",
buildPath: "build/android/",
files: [{ destination: "tokens.xml", format: "android/resources" }],
},
},
});
await sd.buildAllPlatforms();
```
### Custom transform (px → rem)
```typescript
import StyleDictionary from "style-dictionary";
StyleDictionary.registerTransform({
name: "size/pxToRem",
type: "value",
filter: (t) => t.$type === "dimension" && String(t.$value).endsWith("px"),
transform: (t) => `${parseFloat(t.$value) / 16}rem`,
});
```
### Custom format (Tailwind theme extension)
```typescript
StyleDictionary.registerFormat({
name: "tailwind/theme",
format: ({ dictionary }) => {
const colors: Record<string, any> = {};
for (const t of dictionary.allTokens) {
if (t.$type !== "color") continue;
const path = t.path.join(".");
colors[path] = t.$value;
}
return `module.exports = ${JSON.stringify({ theme: { extend: { colors } } }, null, 2)};`;
},
});
```
### Theme variants (light/dark)
```typescript
// tokens/themes/light.json — refs color/blue/500
// tokens/themes/dark.json — overrides
const themes = ["light", "dark"];
for (const theme of themes) {
const sd = new StyleDictionary({
source: ["tokens/base/**/*.json", `tokens/themes/${theme}.json`],
platforms: {
css: {
transformGroup: "css",
buildPath: "build/css/",
files: [{
destination: `${theme}.css`,
format: "css/variables",
options: { selector: `[data-theme=${theme}]` },
}],
},
},
});
await sd.buildAllPlatforms();
}
```
### CI/CD pipeline (GitHub Actions)
```yaml
# .github/workflows/tokens.yml
name: Build Tokens
on:
push:
branches: [main]
paths: ["tokens/**", "config.ts"]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22, cache: pnpm }
- run: pnpm install --frozen-lockfile
- run: pnpm tsx config.ts
- name: Commit built tokens
run: |
git config user.name "tokens-bot"
git config user.email "bot@example.com"
git add build/
git diff --cached --quiet || git commit -m "chore(tokens): rebuild [skip ci]"
git push
```
### Figma → Tokens Studio → SD
```bash
# tokens-studio plugin pushes to GitHub:
# tokens.json (single file)
# SD config consumes via custom parser
npx @tokens-studio/sd-transforms init
```
```typescript
import StyleDictionary from "style-dictionary";
import { register } from "@tokens-studio/sd-transforms";
register(StyleDictionary, { excludeParentKeys: true });
const sd = new StyleDictionary({
source: ["tokens.json"],
preprocessors: ["tokens-studio"],
platforms: { css: { /* ... */ } },
});
```
### Validation step
```typescript
// scripts/validate-tokens.ts
import { readFileSync } from "node:fs";
import { z } from "zod";
const TokenSchema = z.object({
$value: z.union([z.string(), z.number()]),
$type: z.enum(["color", "dimension", "fontFamily", "fontWeight", "duration"]),
});
function walk(obj: any, path: string[] = []) {
if ("$value" in obj) {
TokenSchema.parse(obj);
return;
}
for (const [k, v] of Object.entries(obj)) walk(v, [...path, k]);
}
walk(JSON.parse(readFileSync("tokens.json", "utf-8")));
console.log("매 tokens valid");
```
### Storybook integration
```typescript
// .storybook/preview.ts
import "../build/css/light.css";
import "../build/css/dark.css";
export const globalTypes = {
theme: {
name: "Theme",
defaultValue: "light",
toolbar: { items: ["light", "dark"] },
},
};
export const decorators = [
(Story, ctx) => {
document.documentElement.dataset.theme = ctx.globals.theme;
return Story();
},
];
```
## 매 결정 기준
| 상황 | Approach |
|---|---|
| Web only, simple | CSS vars + Tailwind theme |
| Web + iOS + Android | **Style Dictionary** |
| Figma 동기화 필수 | Tokens Studio + SD |
| 1-person project | 매 overkill — CSS vars 직접 |
| Theme variants | per-theme builds + selector |
**기본값**: Style Dictionary v4 + DTCG JSON + GitHub Actions + multi-platform output. Figma 동기화면 Tokens Studio 추가.
## 🔗 Graph
- 부모: [[Design Tokens]] · [[Design System]]
- 변형: [[Tokens Studio]]
- Adjacent: [[Figma Variables]] · [[CSS_Architecture_and_Styling|CSS Variables]]
## 🤖 LLM 활용
**언제**: design system bootstrap, multi-platform theming, Figma → code pipeline.
**언제 X**: 매 single-file CSS vars 면 충분한 작은 site. Component-only library without theming.
## ❌ 안티패턴
- **Hard-coded colors**: 매 token 우회 → consistency 무너짐.
- **No reference layer**: 매 component token 이 직접 hex → theme 변경 어려움.
- **Manual sync from Figma**: 매 design drift. 매 Tokens Studio + plugin.
- **No CI build**: 매 local 만 build → mismatched committed output.
- **Token explosion**: 매 100s of brand-specific tokens 양산. Hierarchical reference 사용.
## 🧪 검증 / 중복
- Verified (style-dictionary v4 docs, DTCG spec draft, 2026).
- 신뢰도 A.
## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — Style Dictionary pipelines canonical full content |