Files
2nd/10_Wiki/Topics/Architecture/Component Library Architecture.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

6.5 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-component-library-architecture Component Library Architecture 10_Wiki/Topics verified self
Design System Architecture
UI Library Design
none A 0.9 applied
components
design-system
react
shadcn
radix
2026-05-10 pending
language framework
typescript react-radix-shadcn

Component Library Architecture

매 한 줄

"매 unstyled headless primitives + 매 style layer + 매 composition API.". 2026년 React component library 의 dominant model = Radix/Ark UI (headless behavior + a11y) + Tailwind/CSS variables (theming) + shadcn/ui (copy-not-install) + tokens (DTCG). MUI 5 의 monolithic theme 시대 → headless 시대로 매 shift.

매 핵심

매 3 layer architecture

  1. Behavior layer (headless): a11y, keyboard, focus, ARIA — Radix, Ark UI, React Aria.
  2. Style layer: Tailwind, CSS-in-JS (vanilla-extract), CSS variables.
  3. Composition layer: app-specific compositions of 1+2.

매 distribution model

  • Package install (MUI, Chakra v3): npm install, version locked, hard to customize.
  • Copy-paste (shadcn/ui): generator copies source into your repo, you own it, fully customizable.
  • Hybrid (Radix + custom wrapper): primitives via npm, your styles in repo.

매 token system (DTCG / Style Dictionary)

  • Primitive tokens (color.blue.500 = #3b82f6).
  • Semantic tokens (color.action.primary = color.blue.500).
  • Component tokens (button.bg.primary = color.action.primary).

매 응용

  1. Internal design system (Vercel Geist, GitHub Primer).
  2. Open-source kits (shadcn/ui, Mantine, Park UI).
  3. White-label products (multi-brand 동일 codebase).
  4. Cross-framework via Web Components (Spectrum Web Components).

💻 패턴

Headless primitive (Radix)

import * as Dialog from '@radix-ui/react-dialog';

export function ConfirmDialog({ open, onClose, onConfirm, children }: Props) {
  return (
    <Dialog.Root open={open} onOpenChange={onClose}>
      <Dialog.Portal>
        <Dialog.Overlay className="fixed inset-0 bg-black/50" />
        <Dialog.Content className="fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-6">
          <Dialog.Title className="text-lg font-semibold">Confirm</Dialog.Title>
          <Dialog.Description>{children}</Dialog.Description>
          <div className="mt-4 flex justify-end gap-2">
            <Dialog.Close className="btn-ghost">Cancel</Dialog.Close>
            <button className="btn-primary" onClick={onConfirm}>OK</button>
          </div>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  );
}

shadcn-style copy-paste component

// components/ui/button.tsx — owned by your repo
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/lib/utils';

const buttonVariants = cva(
  'inline-flex items-center justify-center rounded-md text-sm font-medium transition',
  {
    variants: {
      variant: {
        primary: 'bg-blue-600 text-white hover:bg-blue-700',
        ghost: 'hover:bg-gray-100',
      },
      size: {
        sm: 'h-8 px-3',
        md: 'h-10 px-4',
        lg: 'h-12 px-6',
      },
    },
    defaultVariants: { variant: 'primary', size: 'md' },
  },
);

type Props = React.ButtonHTMLAttributes<HTMLButtonElement>
  & VariantProps<typeof buttonVariants>;

export function Button({ className, variant, size, ...rest }: Props) {
  return (
    <button
      className={cn(buttonVariants({ variant, size }), className)}
      {...rest}
    />
  );
}

Design tokens (DTCG JSON)

{
  "color": {
    "blue": {
      "500": { "$value": "#3b82f6", "$type": "color" }
    },
    "action": {
      "primary": { "$value": "{color.blue.500}", "$type": "color" }
    }
  },
  "space": {
    "4": { "$value": "16px", "$type": "dimension" }
  }
}

CSS variables driven theming

:root {
  --color-primary: #3b82f6;
  --radius-md: 0.5rem;
}

[data-theme='dark'] {
  --color-primary: #60a5fa;
}

.btn-primary {
  background: var(--color-primary);
  border-radius: var(--radius-md);
}

Polymorphic component (asChild pattern)

import { Slot } from '@radix-ui/react-slot';

type Props = {
  asChild?: boolean;
} & React.HTMLAttributes<HTMLElement>;

export function Card({ asChild, ...rest }: Props) {
  const Comp = asChild ? Slot : 'div';
  return <Comp className="rounded-lg border p-4" {...rest} />;
}

// Usage:
<Card asChild>
  <a href="/post/1">Click me</a>
</Card>

Storybook 8 + a11y addon

// Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './button';

const meta: Meta<typeof Button> = {
  component: Button,
  parameters: { a11y: { test: 'error' } },
};
export default meta;

export const Primary: StoryObj<typeof Button> = {
  args: { children: 'Save', variant: 'primary' },
};

매 결정 기준

상황 Approach
Internal design system, full control shadcn/ui copy-paste + Tailwind
Quick prototype, full kit Mantine, Chakra v3
Cross-framework Lit + Web Components
Strong a11y 요구 Radix or React Aria
Multi-brand white-label Token-driven CSS variables

기본값: React 19 + Radix primitives + Tailwind v4 + shadcn/ui structure + DTCG tokens.

🔗 Graph

🤖 LLM 활용

언제: starting design system, refactoring 중복 UI, multi-product/brand consolidation. 언제 X: 1-page landing site (overhead 큼), heavily 3D/canvas UI (HTML primitive 안 맞음).

안티패턴

  • Tightly styled primitives: behavior + style 의 강결합 — replace 시 rewrite 필요.
  • Theme prop drilling: 매 component 가 theme prop 받음 — CSS variables 로.
  • No tokens: hex color 직접 사용 — token system 부재 시 multi-brand 불가.
  • Locked-in vendor library: MUI v3→v5 같은 대규모 breaking change — headless + own styles 가 안전.

🧪 검증 / 중복

  • Verified (shadcn/ui docs 2026 / Radix UI / DTCG W3C draft / React 19 docs).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — 3-layer model + shadcn/Radix/DTCG 패턴