Files
2nd/10_Wiki/Topics/Frontend/Style Dictionary Pipelines.md
T
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

7.8 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-style-dictionary-pipelines Style Dictionary Pipelines 10_Wiki/Topics verified self
Style Dictionary
Design Token Pipeline
Token Build Pipeline
none A 0.9 applied
design-tokens
style-dictionary
design-system
ci-cd
frontend
2026-05-10 pending
language framework
TypeScript 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)

// 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)

// 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)

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)

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)

// 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)

# .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

# tokens-studio plugin pushes to GitHub:
#   tokens.json (single file)
# SD config consumes via custom parser

npx @tokens-studio/sd-transforms init
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

// 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

// .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

🤖 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