Series 08 — 04 of 05
shadcn/ui라는
치트키
디자이너 없는 개발자를 위한 가장 현실적인 답. 컴포넌트 라이브러리가 AI 워크플로우와 만났을 때 일어나는 일.
왜 shadcn/ui인가
2023년 1월, 한 개발자가 Radix UI 위에 Tailwind CSS를 입힌 컴포넌트 모음을 공개했다. 이름은 shadcn/ui. 특별할 것 없는 이 프로젝트가 2년 만에 GitHub Stars 106,000개를 돌파한 이유는 단 하나다. "설치하지 말고, 복사하라."
기존 UI 라이브러리는 블랙박스다. npm install로 설치하고, 문서에 적힌 props를 전달하고, 라이브러리가 제공하는 API 범위 안에서 커스터마이징한다. 버튼의 border-radius를 바꾸고 싶으면 overrideStyles prop을 찾아야 하고, 없으면 강제로 CSS를 덮어써야 한다. MUI에서 DatePicker의 내부 스타일을 고치려고 3시간을 쓴 경험이 있다면, 이 고통을 안다.
shadcn/ui는 이 구조를 뒤집었다. 코드 자체가 프로젝트에 복사된다. button.tsx가 node_modules가 아니라 components/ui/button.tsx에 있다. 수정하고 싶으면 파일을 열고 고치면 된다. 라이브러리 업데이트에 종속되지 않고, 내 프로젝트의 일부로 완전히 소유한다.
이 "copy-paste 패러다임"이 바이브 코딩 시대에 결정적 이점을 만들어냈다. AI 코드 생성 도구에게 "MUI의 Button 컴포넌트를 수정해"라고 하면, AI는 라이브러리 내부 구현을 추측해야 한다. API가 바뀌었을 수도 있고, 버전별 차이가 있을 수도 있다. 하지만 "components/ui/button.tsx를 수정해"라고 하면, AI는 눈앞에 있는 코드를 직접 읽고 고친다. 추측이 필요 없다.
Vercel의 v0.dev가 shadcn/ui 컴포넌트를 기본 출력으로 선택한 것은 우연이 아니다. Claude, Cursor, Copilot 모두 shadcn/ui 코드를 가장 정확하게 생성한다. 훈련 데이터에 가장 많이 포함된 컴포넌트 라이브러리이기 때문이다.
| Library | Approach | AI 궁합 | 커스터마이징 |
|---|---|---|---|
| shadcn/ui | Copy-paste, 코드 소유 | 최적 — 코드가 프로젝트 내부에 존재 | 파일 직접 수정 |
| MUI | npm 패키지, API 소비 | 보통 — 버전별 API 차이로 AI 오류 빈번 | sx prop / theme override |
| Chakra UI | npm 패키지, 토큰 시스템 | 보통 — v2 → v3 마이그레이션으로 혼란 | Theme config |
| Ant Design | npm 패키지, 기업용 | 낮음 — 복잡한 API, 중국어 문서 주류 | ConfigProvider |
| Headless UI | 행동만, 스타일 없음 | 높음 — 스타일 자유도 최대 | 완전 자유 (= 직접 다 해야 함) |
핵심은 이것이다. AI 시대의 UI 라이브러리는 추상화를 줄이는 방향으로 진화한다. 블랙박스가 클수록 AI가 실수할 여지가 넓어진다. shadcn/ui는 추상화를 최소화하고 코드를 프로젝트 안에 노출함으로써, AI가 가장 잘하는 일 — "보이는 코드를 직접 수정하는 것" — 을 가능하게 만들었다.
"라이브러리를 설치하지 말고, 복사하라.
당신이 소유하지 않는 코드는
당신의 것이 아니다."
보일러플레이트라는 지름길
shadcn/ui의 진짜 위력은 생태계에서 나온다. shadcn/ui 위에 인증, 결제, 대시보드, 이메일, 분석까지 미리 구현해놓은 SaaS 스타터킷이 하나의 시장을 형성했다. 디자인이 이미 되어 있는 상태에서 시작하는 것이다.
Marc Lou는 ShipFast라는 Next.js + Tailwind + shadcn 기반 SaaS 보일러플레이트를 만들어 첫 달에 $40,000을 벌었다. 그의 공개 수익은 월 $124,772에 달한다. 보일러플레이트를 파는 사람이 보일러플레이트를 쓰는 사람보다 더 많이 번다는 아이러니는 차치하고, 이 숫자가 증명하는 것은 명확하다. "처음부터 만들지 않겠다"는 수요가 폭발적이다.
보일러플레이트의 가치는 코드가 아니라 의사결정에 있다. "인증은 어떤 라이브러리를 쓸까", "결제 UI는 어디에 놓을까", "대시보드 레이아웃은 어떻게 잡을까" — 이런 수십 가지 디자인/아키텍처 결정이 이미 내려져 있다. 바이브 코더에게 가장 위험한 것은 매 순간 AI에게 새로운 판단을 요구하는 것이다. 결정이 많아질수록 디자인 드리프트가 발생한다.
단, 보일러플레이트에는 함정이 있다. 모든 ShipFast 사용자의 사이트가 ShipFast처럼 보인다. shadcn/ui의 기본 테마가 "그냥 shadcn"인 것과 같은 문제다. 보일러플레이트는 출발점이지 종착점이 아니다. 여기서 시작해서 브랜드를 입혀야 한다. 그 방법이 Part III의 주제다.
기본에서 브랜드로
shadcn/ui의 기본 테마는 의도적으로 무색(neutral)이다. 검정과 흰색, 최소한의 border-radius, zinc 계열 회색. 이것은 설계 철학이다. "아무 브랜드에나 입힐 수 있는 백지"를 제공하겠다는 것이다. 문제는 대부분의 바이브 코더가 이 백지를 그대로 배포한다는 것이다.
shadcn/ui의 모든 시각적 결정은 CSS 변수 11개에 집중되어 있다. 이 11개를 바꾸면 전체 앱의 룩앤필이 바뀐다. 컴포넌트 코드를 하나하나 수정할 필요가 없다.
테마 커스터마이징의 핵심은 세 가지다. 색상 팔레트, 타이포그래피, 간격. 이 세 가지만 바꿔도 "shadcn인 티"는 사라진다.
--foreground: 0 0% 3.9%;
--primary: 0 0% 9%;
--accent: 0 0% 96.1%;
--foreground: 36 7% 10%;
--primary: 4 70% 48%;
--accent: 36 25% 93%;
타이포그래피도 마찬가지다. shadcn/ui는 기본적으로 시스템 폰트(Inter, -apple-system)를 사용한다. 폰트 하나만 바꿔도 인상이 완전히 달라진다. 한국 프로젝트라면 Pretendard Variable이 무난하면서도 세련된 선택이다. 영문에 세리프(Source Serif 4, Georgia)를 혼합하면 에디토리얼 톤이 나온다.
간격과 모서리 반경(border-radius)은 미묘하지만 결정적이다. shadcn/ui 기본 --radius는 0.5rem(8px)이다. 이것을 0으로 바꾸면 날카로운 산업적 느낌, 1rem으로 올리면 부드럽고 친근한 느낌이 된다. 패딩을 1.5배로 늘리면 여유로운 프리미엄 감이 나고, 0.75배로 줄이면 정보 밀도가 높은 대시보드 감이 난다.
색상
--primary와 --background만 바꿔도 전체 톤이 달라진다. HSL 형식이므로 채도(S)와 명도(L)만 조정해도 다양한 변형이 가능하다.
타이포그래피
font-family 하나가 브랜드 인상의 절반을 결정한다. 시스템 폰트를 벗어나는 순간 "기본값"에서 탈출한다.
간격과 곡률
--radius: 0은 Vercel, --radius: 1rem은 Notion. 패딩을 넉넉히 주면 "여백 = 자신감"이라는 디자인 공리가 작동한다.
실전 팁 하나. shadcn Studio(shadcn.studio)를 사용하면 브라우저에서 실시간으로 색상, radius, 간격을 조정하고, 완성된 CSS 변수를 그대로 복사해 globals.css에 붙여넣을 수 있다. AI에게 "이 색상 팔레트로 바꿔줘"라고 하기 전에, shadcn Studio에서 5분 만에 시각적으로 확인하는 것이 훨씬 빠르다.
CSS 변수 11개를 바꾸면
전체 앱의 인상이 바뀐다.
컴포넌트를 고칠 필요가 없다.
React 없이도 되는가
shadcn/ui는 React 전용이다. Radix UI와 Tailwind CSS 위에 구축되어 있고, Next.js와의 통합이 가장 매끄럽다. 그렇다면 React를 쓰지 않는 프로젝트 — vanilla HTML/CSS, Vue, Svelte, 혹은 아예 프레임워크 없는 정적 사이트 — 에서는 어떻게 해야 하는가.
답은 "shadcn/ui의 철학을 빌리되, 구현은 자신의 스택에 맞추는 것"이다.
| Stack | shadcn 대안 | 특징 |
|---|---|---|
| Vue | shadcn-vue | 공식 Vue 포트. Radix Vue 기반, API 거의 동일 |
| Svelte | shadcn-svelte | Bits UI 기반, Svelte 5 지원. 생태계 빠르게 성장 중 |
| Vanilla | CSS 변수 시스템 | Tailwind/CSS 변수로 직접 디자인 시스템 구축 |
| Astro | shadcn + React islands | 정적 사이트에 인터랙티브 컴포넌트만 React로 삽입 |
프레임워크 없이 성공한 대표 사례가 있다. Pieter Levels는 vanilla HTML, jQuery, 기본 CSS로 Nomad List, Remote OK, PhotoAI를 만들어 월 $250,000 이상을 번다. 그의 기술 스택은 의도적으로 "low-tech"다. React도, Tailwind도, shadcn/ui도 쓰지 않는다.
Levels의 전략은 이렇다. "의도적으로 못생기게 시작하라." 기능이 검증되기 전에 디자인에 시간을 쓰지 않는다. MVP가 트래픽을 만들면 그때 디자인을 개선한다. 그의 사이트는 2024년까지도 Bootstrap 느낌이었지만, 사용자가 돈을 내는 데는 아무 문제가 없었다.
이 접근법은 극단적이지만 핵심 교훈이 있다. 디자인 시스템은 프레임워크가 아니라 규칙이다. React를 쓰든, vanilla HTML을 쓰든, 핵심은 동일하다:
CSS 변수로 토큰 정의
색상, 폰트, 간격을 변수로 선언한다. 프레임워크에 종속되지 않는 가장 기본적인 디자인 시스템.
규칙 파일에 문서화
CLAUDE.md나 AGENTS.md에 토큰 값과 사용 규칙을 기록한다. AI가 참조해서 일관된 코드를 생성한다.
컴포넌트 패턴 반복
버튼, 카드, 폼 등 반복되는 패턴을 CSS 클래스로 정의한다. React가 없어도 재사용 가능한 UI 단위를 만든다.
이 시리즈의 에디토리얼 프로젝트가 정확히 이 방식이다. React도 Tailwind도 없는 순수 HTML + CSS 프로젝트에서, CSS 변수 8개(--bg, --fg, --accent, --muted, --rule, --card-bg, --prose, --secondary)와 CLAUDE.md 스킬 시스템으로 30개 이상의 콘텐츠 페이지가 일관된 디자인을 유지한다.
결론은 이것이다. shadcn/ui는 React 생태계에서 가장 강력한 선택이다. 하지만 그 핵심 원리 — CSS 변수 기반 토큰, 코드 소유, AI 친화적 구조 — 는 어떤 기술 스택에서든 적용 가능하다. 중요한 것은 도구가 아니라 규칙이 있느냐 없느냐다.
디자인 시스템은 프레임워크가 아니라
규칙이다.
도구는 답을 모른다.
규칙이 답을 만든다.
shadcn/ui든 vanilla CSS든, 일관성의 열쇠는 CSS 변수 몇 개와 그것을 지키겠다는 결정에 있다.