--- id: wiki-2026-0508-디자인-시스템-구축 title: 디자인 시스템 구축 category: 10_Wiki/Topics status: verified canonical_id: self aliases: [Design System, Component Library, UI Kit, Design Tokens] duplicate_of: none source_trust_level: A confidence_score: 0.9 verification_status: applied tags: [frontend, design-system, components, tokens, storybook] raw_sources: [] last_reinforced: 2026-05-10 github_commit: pending tech_stack: language: typescript framework: react --- # 디자인 시스템 구축 ## 매 한 줄 > **"매 product 가 아닌 product 를 만드는 platform"**. Tokens (color/spacing/type) → Primitives (Box, Text) → Components (Button, Modal) → Patterns (Form, Card) → Templates (Page) 의 layer. 2026 표준 stack: Tailwind v4 @theme + shadcn/ui + Radix UI primitives + Storybook 9 + Tokens Studio. ## 매 핵심 ### 매 layer 구조 1. **Tokens**: design primitives — color, spacing, type, radii, shadow, motion. CSS variable / JSON. 2. **Primitives** (headless): Radix UI / Ariakit — accessibility 보장, unstyled. 3. **Components**: tokens + primitives → branded — Button, Input, Dialog. 4. **Patterns**: composed components — DataTable, Form, Wizard. 5. **Templates / Pages**: full layouts. ### 매 핵심 결정 - **Headless vs styled**: Radix (headless) + own styles → flex 좋음. Material UI (styled) → 빠른 시작. - **Distribution**: NPM package (`@acme/ui`) vs copy-paste (shadcn/ui). - **Theme**: light/dark/brand variants — CSS variable 가 표준. - **A11y**: 매 Radix/Ariakit 사용으로 무료 — 매 직접 구현 X. ### 매 응용 1. Multi-product company (Atlassian, Shopify Polaris, IBM Carbon). 2. Open source DS (shadcn/ui, Material UI, Mantine). 3. Internal admin tool DS. 4. Marketing + app split (display 강조 + utility). ## 💻 패턴 ### Token foundation (Tailwind v4 @theme) ```css @import "tailwindcss"; @theme { --color-bg: oklch(1 0 0); --color-fg: oklch(0.2 0 0); --color-primary: oklch(0.7 0.2 250); --color-danger: oklch(0.65 0.25 25); --spacing: 0.25rem; /* base unit */ --radius-sm: 0.25rem; --radius-md: 0.5rem; --radius-lg: 1rem; --font-sans: 'Inter Variable', system-ui; --shadow-sm: 0 1px 2px oklch(0 0 0 / 0.05); --shadow-md: 0 4px 12px oklch(0 0 0 / 0.1); --ease-out: cubic-bezier(0.16, 1, 0.3, 1); } /* 매 dark theme */ @media (prefers-color-scheme: dark) { @theme { --color-bg: oklch(0.15 0 0); --color-fg: oklch(0.95 0 0); } } ``` ### Headless primitive + style (shadcn/ui pattern) ```tsx // components/ui/dialog.tsx import * as DialogPrimitive from '@radix-ui/react-dialog'; import { cn } from '@/lib/cn'; export const Dialog = DialogPrimitive.Root; export const DialogTrigger = DialogPrimitive.Trigger; export const DialogContent = forwardRef( ({ className, children, ...props }, ref) => ( {children} ) ); ``` ### Variant API (cva / tailwind-variants) ```ts import { cva, type VariantProps } from 'class-variance-authority'; const button = cva('inline-flex items-center rounded-md font-medium transition', { variants: { variant: { primary: 'bg-primary text-white hover:opacity-90', ghost: 'hover:bg-fg/5', danger: 'bg-danger text-white', }, size: { sm: 'h-8 px-3 text-sm', md: 'h-10 px-4 text-base', lg: 'h-12 px-6 text-lg', }, }, defaultVariants: { variant: 'primary', size: 'md' }, }); export interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps {} export const Button = ({ className, variant, size, ...props }: ButtonProps) =>