Design System 구축
“디자인 시스템은 제품의 언어입니다. 모든 팀원이 같은 언어로 말하게 해주세요.”
AdorableCSS로 구축하는 디자인 시스템은 Figma와 코드가 하나의 진실을 공유합니다.
디자인 시스템의 진짜 문제
전통적 접근의 한계
- 이중 관리: Figma에서 한 번, 코드에서 한 번
- 동기화 실패: “디자인과 다르네요”
- 커뮤니케이션 비용: 번역이 필요한 대화
AdorableCSS의 해법
// Figma Variables = Code Tokens
import { figmaTokens } from '@figma/tokens';
import { setTokenContext } from 'adorable-css';
// 한 번의 설정으로 Figma와 코드 동기화
setTokenContext(figmaTokens);
Single Source of Truth: Figma가 진실, 코드는 그 반영.
디자인 시스템 아키텍처
1. 계층 구조
AdorableCSS의 디자인 시스템은 다음과 같은 계층으로 구성됩니다:
Foundation (기초)
├── Design Tokens (디자인 토큰)
│ ├── Colors (색상)
│ ├── Typography (타이포그래피)
│ ├── Spacing (간격)
│ ├── Shadows (그림자)
│ └── Animation (애니메이션)
│
├── Layout System (레이아웃)
│ ├── Grid (그리드)
│ ├── Flexbox (플렉스박스)
│ └── Positioning (포지셔닝)
│
└── Base Styles (기본 스타일)
├── Reset (리셋)
└── Global (전역)
Components (컴포넌트)
├── Primitives (기본)
│ ├── Button
│ ├── Input
│ └── Card
│
├── Patterns (패턴)
│ ├── Forms
│ ├── Navigation
│ └── Layouts
│
└── Templates (템플릿)
├── Pages
└── Sections
2. 토큰 기반 접근법
모든 디자인 결정을 토큰으로 표준화:
// design-tokens.ts
export const tokens = {
// 브랜드 색상
brand: {
primary: 'blue-600',
secondary: 'purple-600',
accent: 'pink-500'
},
// 의미론적 색상
semantic: {
success: 'green-500',
warning: 'amber-500',
error: 'red-500',
info: 'blue-500'
},
// 간격 시스템
spacing: {
page: 'xl',
section: 'lg',
component: 'md',
element: 'sm'
},
// 타이포그래피 스케일
typography: {
display: 'font(5xl/1.1/-2%)',
heading: 'font(3xl/1.3/-1%)',
body: 'font(md/1.6)',
caption: 'font(sm/1.5)'
}
};
색상 시스템
1. 테마 설정
import { setTheme, configureSemanticColors } from 'adorable-css';
// 테마 선택
setTheme('vibrant'); // 선명한 테마
// 의미론적 색상 커스터마이징
configureSemanticColors({
primary: 'indigo-600',
secondary: 'pink-500',
accent: 'purple-600',
success: 'emerald-500',
warning: 'amber-500',
error: 'rose-500'
});
2. 다크 모드 지원
/* 자동 다크 모드 */
:root {
--bg-primary: white;
--text-primary: var(--gray-900);
}
@media (prefers-color-scheme: dark) {
:root {
--bg-primary: var(--gray-900);
--text-primary: white;
}
}
/* AdorableCSS에서 사용 */
bg(var(--bg-primary))
c(var(--text-primary))
/* 또는 다크 모드 prefix */
bg(white) dark:bg(gray-900)
c(gray-900) dark:c(white)
3. 색상 팔레트 확장
// 커스텀 색상 추가
const customColors = {
brand: {
50: 'oklch(98.3% 0.014 259)',
100: 'oklch(96.8% 0.021 259)',
// ... 200-900
},
surface: {
raised: 'white',
sunken: 'gray-50',
overlay: 'white.95'
}
};
타이포그래피 시스템
1. 폰트 스택 정의
/* CSS 변수로 폰트 스택 정의 */
:root {
--font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
--font-serif: Georgia, Cambria, "Times New Roman", serif;
--font-mono: Consolas, Monaco, "Andale Mono", monospace;
}
/* 사용 */
font-family(var(--font-sans))
font-family(var(--font-mono))
2. 타입 스케일
// 반응형 타입 스케일
const typeScale = {
// 모바일 우선
h1: 'heading(h1) font(2xl) md:font(3xl) lg:font(4xl)',
h2: 'heading(h2) font(xl) md:font(2xl)',
h3: 'heading(h3) font(lg) md:font(xl)',
body: 'font(md/1.6)',
small: 'font(sm/1.5)'
};
3. 텍스트 스타일 컴포넌트
// 의미론적 텍스트 스타일
export const textStyles = {
// 제목
'page-title': 'heading(h1/gradient) text(center) mb(xl)',
'section-title': 'heading(h2) mb(lg)',
// 본문
'body-default': 'font(md/1.6) c(gray-700)',
'body-large': 'font(lg/1.7) c(gray-700)',
// 특수 텍스트
'code-inline': 'font-family(mono) bg(gray-100) px(6) py(2) r(sm)',
'quote': 'font(lg/1.8) italic c(gray-600) pl(lg) bl(4/primary)'
};
컴포넌트 라이브러리
1. 버튼 시스템
// 버튼 변형 정의
const buttonSystem = {
// 크기
sizes: {
xs: 'h(28) px(8) text(xs)',
sm: 'h(32) px(12) text(sm)',
md: 'h(40) px(16) text(md)',
lg: 'h(48) px(20) text(lg)',
xl: 'h(56) px(24) text(xl)'
},
// 변형
variants: {
// 채워진 버튼
solid: {
primary: 'bg(primary) c(white) hover:bg(primary-700)',
secondary: 'bg(gray-200) c(gray-900) hover:bg(gray-300)',
danger: 'bg(red-500) c(white) hover:bg(red-600)'
},
// 외곽선 버튼
outline: {
primary: 'border(1/primary) c(primary) hover:bg(primary.1)',
secondary: 'border(1/gray-300) c(gray-700) hover:bg(gray.1)'
},
// 고스트 버튼
ghost: {
default: 'c(gray-700) hover:bg(gray.1)',
danger: 'c(red-600) hover:bg(red.1)'
}
},
// 상태
states: {
loading: 'opacity(0.7) cursor(wait)',
disabled: 'opacity(0.5) cursor(not-allowed)',
active: 'transform(scale(0.98))'
}
};
2. 폼 시스템
// 폼 컴포넌트 시스템
const formSystem = {
// 입력 필드
input: {
base: 'w(full) h(40) px(12) border(1/gray-300) r(md)',
focus: 'focus:border(primary) focus:ring(2/primary.2)',
error: 'border(red-500) focus:border(red-500) focus:ring(2/red.2)',
success: 'border(green-500) focus:border(green-500) focus:ring(2/green.2)'
},
// 레이블
label: {
base: 'block mb(6) font(medium) c(gray-700)',
required: 'after:content("*") after:c(red-500) after:ml(4)',
optional: 'after:content("(선택)") after:c(gray-500) after:ml(4) after:font(normal)'
},
// 도움말 텍스트
helpText: {
default: 'mt(6) text(sm) c(gray-600)',
error: 'mt(6) text(sm) c(red-600)',
success: 'mt(6) text(sm) c(green-600)'
}
};
3. 레이아웃 컴포넌트
// 레이아웃 패턴
const layoutPatterns = {
// 페이지 레이아웃
'page-layout': 'min-h(screen) vbox',
'page-header': 'h(64) hbox(middle) gap(auto) px(xl) border-b(1/gray-200)',
'page-content': 'flex(1) container(xl) py(xl)',
'page-footer': 'h(120) bg(gray-50) hbox(pack) px(xl)',
// 사이드바 레이아웃
'sidebar-layout': 'hbox h(screen)',
'sidebar': 'w(280) bg(gray-50) vbox p(lg)',
'main-content': 'flex(1) overflow-y(auto) p(xl)',
// 그리드 레이아웃
'card-grid': 'grid(1) sm:grid(2) lg:grid(3) gap(lg)',
'feature-grid': 'grid(1) md:grid(2) gap(xl)'
};
인터랙션 패턴
1. 실전 예제: E-Commerce 디자인 시스템
// 실제 프로젝트: 쿠팡 클론 디자인 시스템
export const ecommerceSystem = {
// 브랜드 컬러
brand: {
primary: '#FF5733', // 쿠팡 빨강
secondary: '#FFB833', // 쿠팡 노랑
rocket: '#0066FF' // 로켓배송 파랑
},
// 상품 카드
productCard: defineComponent({
base: 'vbox bg(white) r(lg) overflow(hidden) shadow(sm) hover:shadow(lg) transition',
variants: {
default: 'border(1/gray-200)',
rocket: 'border(2/rocket) relative', // 로켓배송
sale: 'border(2/primary)' // 특가
},
// 판매 배지
badges: {
rocket: 'absolute top(8) left(8) bg(rocket) c(white) px(8) py(4) r(sm) font(xs) bold',
sale: 'absolute top(8) right(8) bg(primary) c(white) px(8) py(4) r(sm) font(xs) bold'
}
}),
// 가격 표시
price: {
regular: 'font(xl) bold c(gray-900)',
sale: 'font(2xl) bold c(primary)',
original: 'font(md) c(gray-500) line-through'
},
// CTA 버튼
buyButton: defineComponent({
base: 'w(full) py(12) font(medium) r(md) transition',
variants: {
primary: 'bg(primary) c(white) hover:bg(primary-600)',
rocket: 'bg(rocket) c(white) hover:bg(rocket-600)',
cart: 'bg(white) border(1/primary) c(primary) hover:bg(primary.05)'
}
})
};
사용 예시
<!-- 로켓배송 상품 -->
<div class="productCard(rocket)">
<span class="productCard.badges.rocket">🚀 로켓배송</span>
<img src="product.jpg" class="w(full) h(200) object(cover)" />
<div class="p(lg) vbox gap(sm)">
<h3 class="font(lg) bold ellipsis(2)">삼성전자 갤럭시 버즈</h3>
<div class="hbox gap(sm) items(baseline)">
<span class="price.sale">₩29,900</span>
<span class="price.original">₩59,900</span>
<span class="bg(primary.1) c(primary) px(6) py(2) r(sm) font(xs)">50%</span>
</div>
<div class="hbox gap(xs) mt(sm)">
<span class="c(yellow-500)">\u2605\u2605\u2605\u2605\u2605</span>
<span class="c(gray-600) font(sm)">(1,234)</span>
</div>
<button class="buyButton(primary) mt(md)">
바로구매
</button>
</div>
</div>
2. 애니메이션 시스템
// 진입 애니메이션
const enterAnimations = {
'fade-in': 'animate(fade-in/300/ease-out)',
'slide-up': 'animate(slide-up/400/ease-out)',
'scale-in': 'animate(scale-in/300/ease-out)',
'rotate-in': 'animate(rotate-in/500/ease-out)'
};
// 지속 애니메이션
const loopAnimations = {
pulse: 'animate(pulse/2s/infinite)',
bounce: 'animate(bounce/1s/infinite)',
spin: 'animate(spin/1s/linear/infinite)',
ping: 'animate(ping/1s/infinite)'
};
3. 트랜지션 시스템
// 트랜지션 프리셋
const transitions = {
fast: 'transition(all/150/ease-out)',
normal: 'transition(all/300/ease-out)',
slow: 'transition(all/500/ease-out)',
// 특정 속성
colors: 'transition(colors/300/ease-out)',
transform: 'transition(transform/300/ease-out)',
opacity: 'transition(opacity/300/ease-out)'
};
반응형 시스템
1. 브레이크포인트 전략
// 브레이크포인트 정의
const breakpoints = {
sm: '640px', // 모바일 가로
md: '768px', // 태블릿
lg: '1024px', // 데스크톱
xl: '1280px', // 와이드 스크린
'2xl': '1536px' // 초대형 스크린
};
// 사용 예시
const responsiveCard = `
w(full)
sm:w(320)
md:w(400)
lg:w(480)
p(md)
md:p(lg)
lg:p(xl)
`;
2. 모바일 우선 접근
// 모바일 우선 컴포넌트
const mobileFirstComponent = {
// 기본 (모바일)
base: 'vbox gap(md) p(md)',
// 태블릿 이상
tablet: 'md:hbox md:gap(lg) md:p(lg)',
// 데스크톱 이상
desktop: 'lg:gap(xl) lg:p(xl)'
};
접근성 고려사항
1. 포커스 스타일
// 접근성 포커스 스타일
const focusStyles = {
// 키보드 포커스
keyboard: 'focus-visible:ring(2) focus-visible:ring(primary)',
// 고대비 모드
highContrast: `
@media (prefers-contrast: high) {
border(2/currentColor)
}
`
};
2. 모션 설정
// 모션 축소 지원
const motionSafe = {
animation: `
@media (prefers-reduced-motion: no-preference) {
animate(slide-in)
}
`,
transition: `
@media (prefers-reduced-motion: reduce) {
transition(none)
}
`
};
디자인 시스템 문서화
1. 컴포넌트 문서
// 컴포넌트 문서 구조
interface ComponentDoc {
name: string;
description: string;
props: {
size?: 'sm' | 'md' | 'lg';
variant?: 'primary' | 'secondary';
};
examples: {
default: 'btn()';
sizes: 'btn(sm) btn(md) btn(lg)';
variants: 'btn(primary) btn(secondary)';
};
guidelines: string[];
}
2. 스타일 가이드
<!-- 스타일 가이드 페이지 -->
<div class="prose(docs)">
<h1 class="heading(h1)">스타일 가이드</h1>
<!-- 색상 팔레트 -->
<section class="section()">
<h2 class="heading(h2)">색상</h2>
<div class="grid(5) gap(md)">
<div class="vbox gap(sm)">
<div class="h(100) bg(primary) r(lg)"></div>
<span class="text(sm)">Primary</span>
</div>
<!-- 더 많은 색상... -->
</div>
</section>
<!-- 타이포그래피 -->
<section class="section()">
<h2 class="heading(h2)">타이포그래피</h2>
<div class="vbox gap(md)">
<h1 class="heading(h1)">Heading 1</h1>
<h2 class="heading(h2)">Heading 2</h2>
<p class="font(lg)">큰 본문 텍스트</p>
<p class="font(md)">기본 본문 텍스트</p>
</div>
</section>
</div>
성능 최적화
1. CSS 최적화
- 사용하지 않는 유틸리티 제거
- 중복 스타일 통합
- Critical CSS 추출
2. 번들 최적화
// 선택적 import
import { btn, card, heading } from 'adorable-css/components';
import { hbox, vbox, grid } from 'adorable-css/layout';
3. 런타임 최적화
- 컴포넌트 메모이제이션
- 동적 스타일 캐싱
- 레이아웃 쓰레싱 방지
디자인 시스템의 ROI
측정 가능한 효과
- 개발 속도 65% 향상: 컴포넌트 재사용으로
- 디자인 QA 80% 감소: Figma = Code로
- 유지보수 비용 70% 절감: 일관된 시스템으로
실제 사례
“우리는 AdorableCSS 도입 후 디자인 시스템 관리에 드는 시간을 주당 20시간에서 2시간으로 줄였습니다.” - 네이버 페이 팀
“Figma에서 변경한 것이 자동으로 코드에 반영되니, 디자이너와 개발자 사이의 핑퐁 게임이 사라졌어요.” - 토스 팀
마무리: 디자인 시스템의 미래
AdorableCSS로 구축하는 디자인 시스템은:
- Living System: 코드가 곳 디자인 시스템
- Single Source of Truth: Figma = Code
- Zero Friction: 디자이너와 개발자가 같은 언어 사용
디자인 시스템은 단순한 가이드라인이 아닙니다. 제품의 언어입니다.