f8b21af4be
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>
284 lines
7.8 KiB
Markdown
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 |
|