frontend

shadcn/ui 완벽 가이드 — Radix UI 기반 복사·붙여넣기 컴포넌트 시스템

npm 패키지 대신 소스 코드를 직접 소유하는 shadcn/ui의 설계 철학과 Tailwind CSS, Radix UI를 결합한 컴포넌트 구성 방법을 상세히 정리하였다.

적극 추천
shadcn/uiRadix UITailwind CSS컴포넌트디자인 시스템
shadcn/ui 완벽 가이드 — Radix UI 기반 복사·붙여넣기 컴포넌트 시스템
  • ·출시: 2023년 (shadcn 개발)
  • ·Star 수: GitHub 70,000+ (2026년 기준)
  • ·패키지 설치 방식이 아닌 소스 코드 복사 방식
  • ·Radix UI Primitives + Tailwind CSS 조합
Chakra UI 기반 디자인 시스템을 shadcn/ui로 교체하면서 가장 큰 변화는 컴포넌트 코드를 직접 소유하게 된 것이었다. 브랜드 색상과 타이포그래피를 CSS 변수 한 곳에서 관리하면서 라이트·다크 모드 유지보수가 크게 단순해졌다. Radix UI의 접근성 처리 덕분에 스크린 리더 테스트에서 지적받던 포커스 관리 이슈가 추가 코드 없이 자동으로 해소되었다.

shadcn/ui의 혁신적 설계 철학

패키지가 아닌 소유(ownership) 모델

shadcn/ui는 npm에서 설치하는 컴포넌트 라이브러리가 아니다. npx shadcn-ui add button 명령을 실행하면 Button 컴포넌트의 소스 코드가 프로젝트의 components/ui/ 폴더에 직접 복사된다. 이 방식은 외부 패키지 버전 업데이트에 의존하지 않고 컴포넌트를 완전히 소유한다는 것을 의미한다. 디자인 요구사항에 맞게 임의로 수정해도 라이브러리 업데이트로 덮어써지는 걱정이 없다. 초기에는 이 방식이 관리하기 어렵다고 느낄 수 있지만, 장기적으로 외부 의존성 잠금(lock-in) 없이 유연하게 커스터마이징할 수 있다는 점이 대규모 팀에서 호평받고 있다.

Radix UI Primitives의 접근성 보장

shadcn/ui 컴포넌트의 기반은 Radix UI가 제공하는 헤드리스 프리미티브이다. Radix UI는 WAI-ARIA 표준을 완벽히 준수하여 키보드 탐색, 스크린 리더 호환성, 포커스 관리를 자동으로 처리한다. 개발자는 스타일링에만 집중하면 되며, 접근성 구현을 처음부터 작성해야 하는 부담이 사라진다. Dialog, Dropdown Menu, Select, Tooltip처럼 복잡한 접근성 패턴이 요구되는 컴포넌트에서 Radix UI의 가치가 특히 두드러진다.

설치와 테마 설정

초기 설정 과정

Next.js 프로젝트에 shadcn/ui를 적용하려면 npx shadcn-ui@latest init 명령을 실행한다. 인터랙티브 프롬프트에서 기본 색상 테마(zinc, slate, blue 등), CSS 변수 사용 여부, components 폴더 경로를 선택하면 components.json 설정 파일과 globals.css에 CSS 변수가 자동으로 생성된다. 이후 npx shadcn-ui add [component-name] 명령으로 필요한 컴포넌트를 하나씩 추가한다. 한 번에 모든 컴포넌트를 추가하는 것보다 필요한 것만 선택적으로 추가하는 것이 번들 크기 관리에 유리하다.

CSS 변수 기반 다크 모드

shadcn/ui는 CSS 변수를 활용하여 라이트·다크 모드를 구현한다. :root에 라이트 모드 색상 변수를 정의하고 .dark 클래스에 다크 모드 변수를 오버라이드하는 방식으로, next-themes 라이브러리와 결합하면 시스템 설정 연동 다크 모드를 빠르게 구현할 수 있다. Tailwind CSS의 dark: 변형 클래스 없이도 컴포넌트가 자동으로 다크 모드에 반응하기 때문에 다크 모드 유지보수 부담이 크게 줄어든다.

커스터마이징과 확장

Class Variance Authority로 변형 관리

shadcn/ui 컴포넌트는 내부적으로 Class Variance Authority(CVA)를 사용하여 버튼의 크기(sm, md, lg)나 스타일(default, destructive, outline)처럼 여러 변형을 체계적으로 관리한다. cva() 함수로 기본 클래스와 변형별 클래스를 선언하면 TypeScript 타입이 자동으로 추론되어 잘못된 variant 값을 빌드 타임에 잡아낼 수 있다. 커스텀 variant를 추가하는 것도 cva 설정에 한 줄을 추가하는 것으로 해결된다.

자주 묻는 질문

shadcn/ui는 Next.js 전용인가요?+

아닙니다. Vite + React, Remix, Astro 등 Tailwind CSS가 동작하는 모든 React 환경에서 사용할 수 있습니다.

컴포넌트 업데이트는 어떻게 하나요?+

shadcn/ui가 컴포넌트를 업데이트하면 npx shadcn-ui@latest add [component] --overwrite 명령으로 새 버전을 덮어쓸 수 있습니다. 단, 직접 수정한 내용은 사라지므로 git diff로 변경사항을 확인하고 수동으로 병합해야 합니다.

관련 글