디자인 시스템 구축 가이드 — 구성요소와 shadcn과 AI 도구
2026-01-15#design-system#shadcn#ai
디자인 시스템의 구성요소는 세가지로 볼수있따. 이셋을 만드는 것과 shadcn/ui 위에 얹는 구체적인 방법, 그리고 AI 도구가 시스템을 지키게 만드는 설정까지 정리했다.
예를들어보자 버튼을 블루 계열의 색상으로 만들때 화면마다 미묘하게 다르다면?
누군가 #3182F6을 복사했고, 누군가는 #3B82F6을 썼다.
모달은 세 명이 세 번 만들어서 세가지의 버전으로 있다면?
이 상태를 끝내는 도구가 디자인 시스템이다.
정의는 간단하다 — 같은 UI 결정을 두 번 하지 않기 위한 장치.
디자인 시스템의 구성요소 세 가지#
디자인 시스템은 보통 세 개의 층으로 정리한다. KRDS(대한민국 정부 디자인 시스템)나 LINE 디자인 시스템 같은 공개 사례들도 같은 구조다.
- 원칙(Principles) — 판단 기준. "무엇이 우리다운 화면인가"에 대한 답을 문장으로 적은 것. "위험한 작업은 반드시 한 번 더 확인받는다" 같은 문장.
- 파운데이션(Foundations) — 디자인 언어의 최소 단위. 색,
타이포그래피, 간격, 모서리 라운드, 아이콘. 코드에서는 이
값들에 이름을 붙인 디자인 토큰이 된다 —
#3182F6이 아니라--primary. - 컴포넌트(Components) — 파운데이션을 조립해 만든 재사용 UI. Button, Input, Dialog.
파운데이션 없는 컴포넌트는 색을 하드코딩하고, 컴포넌트 없는 파운데이션은 쓸 곳이 없고, 원칙 없는 시스템은 같은 컴포넌트를 사람마다 다르게 쓴다.
원칙(Principles)#
원칙이라고 해서 브랜드 철학 문서를 쓰는 게 아니다. 팀이 UI를 놓고 의견이 갈릴 때 판정 기준이 되는 문장 몇 개면 충분하다.
- 한 화면에 강조 버튼은 하나만 둔다.
- 삭제·결제처럼 되돌릴 수 없는 작업은 확인 단계를 거친다.
- 본문 텍스트는 최소 14px. 줄이지 않는다.
이 문장들이 있어야 뒤에서 만들 파운데이션과 컴포넌트에 "왜"가 생긴다.
destructive variant가 존재하는 이유가 곧 두 번째 문장이다.
파운데이션(Foundations)#
파운데이션의 값들을 코드로 옮기는 형식이 디자인 토큰이고, 가장 검증된 방법은 primitive와 semantic 두 단계로 나누는 것이다.
:root {
/* primitive — 값 자체. 팔레트를 나열한다 */
--blue-500: #3182f6;
--red-500: #f04452;
--gray-100: #f2f4f6;
/* semantic — 용도. primitive를 참조한다 */
--primary: var(--blue-500);
--destructive: var(--red-500);
--muted: var(--gray-100);
}컴포넌트는 semantic만 쓴다. 이 한 겹의 간접 참조가 주는 이점은 아주 많다.
브랜드 색을 파랑에서 초록으로 바꾼다고 가정하면, 고치는 곳은
--primary: var(--green-500) 한 줄이다. 화면 200개를 뒤져야 했을수도 있는게
CSS 한 줄이 된다.
토큰 이름은 디자이너의 Figma variables와 글자까지 똑같이
맞추는게 좋다. Figma에 primary가 있으면 코드에도 --primary다. 이름이
같아야 "여기 primary로 바꿔주세요"라는 소통또한 자연스럽게 이루어진다.
컴포넌트(Components)#
컴포넌트를 컨트롤할때는 boolean prop 조합이 아니라 속성props의 속성값으로 만든다.
속성값은 디자이너와 함께 정하는게 좋다. 디자이너가 "고스트 버튼"
이라고 부르면 코드도 ghost인것이다. 이 목록이 곧 팀의 어휘가 된다.
만드는 순서는 사용 빈도순이다. Button → Input → Select → Dialog. 전체 목록을 다 갖추고 나서 쓰기 시작하는 게 아니라, 하나가 완성되면 그 하나부터 실제 화면에 투입한다.
원칙은 코드와 같이 세팅해둔다.#
원칙과 사용 규칙을 별도 위키에만 쓰면 아무도 안 읽는다. 원칙은 코드에서 가장 가까운에 있어야한다.
— 주석, 레포의 README, 그리고 뒤에서 다룰 AI 규칙 파일.
"위험한 작업의 확인 버튼은 destructive", "한 화면에 default 버튼은 하나만"
처럼 원칙을 컴포넌트의 언어로 번역한 문장이면 충분하다.
이 셋을 shadcn 위에 얹기#
shadcn/ui는 요즘 React 프로젝트에서
사실상 표준이 된 컴포넌트 도구다. npm 패키지가 아니라서 설치
방식이 다르다 — npx shadcn add button을 실행하면 버튼의 소스
코드가 내 레포의 components/ui/button.tsx로 복사된다. 의존성이
아니라 내 코드가 된다.
이 구조가 디자인 시스템과 잘 맞는 이유는, 위에서 말한 세 요소가 전부 수정 가능한 파일로 손에 들어오기 때문이다.
파운데이션은 이렇게 넣는다 — shadcn은 --background, --primary,
--destructive 같은 semantic 변수 체계를 이미 갖고 있고, 모든
컴포넌트가 이 변수만 참조한다. 할 일은 globals.css에서 이
변수들에 우리 팔레트를 채우는 것이다. 위의 2단계 토큰 구조가
그대로 들어간다.
컴포넌트는 이렇게 고친다 — button.tsx를 열면
cva로 선언된 variant 목록이 있다.
const buttonVariants = cva('...', {
variants: {
variant: {
default: 'bg-primary text-primary-foreground',
destructive: 'bg-destructive text-white',
outline: 'border bg-background',
// 우리 디자인에 없는 variant는 지우고,
// 필요한 variant는 여기 추가한다
},
},
})npm 라이브러리였다면 wrapper를 만들고 스타일을 덮어쓰는 작업이지만, shadcn에서는 그냥 내 파일을 수정하는 일이다. 지운 variant는 팀 누구도 못 쓴다 — 닫힌 목록이 강제된다.
다른 프로젝트에는 이렇게 나눠준다 — 프로젝트가 여러 개라면 다듬은 컴포넌트를
레지스트리로 배포할 수
있다. 레포에 registry.json을 정의해두면 다른 프로젝트에서
npx shadcn add @our-org/button으로 설치한다. 공용 npm 패키지의
빌드·버저닝 작업 없이 배포 경로가 생긴다.
AI 도구가 시스템을 지키게 만들기#
Cursor, Claude Code 같은 AI 코딩 도구는 레포의 코드를 읽고 거기 있는 패턴을 따라 쓴다. shadcn 컴포넌트는 패키지 안에 있지 않고 레포안의 파일이라서 AI가 전부 읽을 수 있다. 즉 디자인 시스템이 코드로 존재하면, AI의 결과물도 시스템을 따른다. 이걸 확실하게 만드는 설정이 세 가지 있다.
1. AI 규칙 파일에 시스템을 명시한다. Claude Code는
CLAUDE.md, Cursor는 .cursorrules를 읽는다. 원칙과 사용 규칙을
여기에 적으면 모든 AI 세션이 그 규칙 아래서 코드를 쓴다.
## UI 규칙
- 색상은 semantic 변수만 사용한다. hex 값 하드코딩 금지.
- 버튼은 components/ui/button.tsx를 사용한다.
새 버튼 컴포넌트를 만들지 않는다.
- variant 추가가 필요하면 buttonVariants에 추가하고
디자이너 리뷰를 받는다.2. 토큰 밖의 값을 lint로 차단한다. AI도 사람처럼 lint에
걸린다. text-[#3182f6] 같은 arbitrary value를 ESLint 규칙으로
막아두면, AI가 규칙 파일을 무시하고 hex를 쓰더라도 CI에서 잡힌다.
규칙 파일이 "권고"라면 lint는 "강제"다.
3. 레지스트리를 AI에 연결한다. shadcn 레지스트리는 MCP(Model
Context Protocol) 서버로 노출할 수 있다. 연결해두면 AI 도구가
"우리 조직에 어떤 컴포넌트가 있는지"를 직접 조회하고, 새로 만드는
대신 add 명령으로 설치한다. 사내 컴포넌트가 있는 줄 몰라서 또
만드는 문제 — 사람도 AI도 똑같이 겪는 그 문제가 막힌다.
요약#
- 디자인 시스템 = 원칙 + 파운데이션 + 컴포넌트. 셋 다 있어야 작동한다.
- 원칙은 판정 기준 문장 몇 개, 파운데이션은 primitive/semantic 두 단계 토큰, 컴포넌트의 variant는 닫힌 목록. 원칙은 코드 옆에 두고, 컴포넌트는 사용 빈도순으로 만든다.
- shadcn은 이 셋을 전부 내 레포의 파일로 소유하게 해준다. 토큰은
globals.css, variant는 cva 선언, 배포는 레지스트리. - AI 도구에는 규칙 파일로 알려주고, lint로 강제하고, 레지스트리를 연결한다. 코드로 존재하는 시스템만 AI가 지킨다.