스타일이 고정된 UI 라이브러리를 사용하다 보면, 디자인 시스템에 맞게 커스터마이징할 때 매번 오버라이드하거나 래핑해야 하는 번거로움이 있습니다.
shadcn/ui는 이러한 문제를 해결하기 위해, NPM 패키지 뒤에 숨겨진 컴포넌트 코드를 공개하여 직접 복사·붙여넣기로 시작해 마음껏 수정할 수 있도록 설계된 새로운 접근 방식을 제안합니다.
일반적인 컴포넌트 라이브러리는 NPM에서 패키지를 설치하고, 컴포넌트를 임포트한 후 앱에서 사용하는 방식으로 작동합니다.
이 접근법은 디자인 시스템에 맞게 컴포넌트를 커스터마이징하거나 라이브러리에 포함되지 않은 컴포넌트가 필요할 때까지는 잘 작동합니다.
그러나 대부분의 경우 라이브러리 컴포넌트를 래핑하고, 스타일을 오버라이드하기 위한 코드를 작성하거나, 호환되지 않는 API를 가진 다른 라이브러리의 컴포넌트를 혼합해서 사용하게 됩니다.
프레임워크도, 일반 라이브러리도 아닌 코드 배포 플랫폼
Next.js나 React 같은 프레임워크, 또는 Material UI·Chakra UI 같은 전통적인 컴포넌트 라이브러리와 달리, shadcn/ui는 개별 컴포넌트 소스 파일을 선택해 내 프로젝트에 가져오는 템플릿 역할을 합니다.
NPM 설치가 아닌, CLI로 필요한 컴포넌트를 프로젝트에 복사한 뒤 직접 커스터마이징할 수 있습니다.
표준 기술 스택 기반
접근성 보장을 위한 Radix UI 프리미티브와 스타일링을 위한 Tailwind CSS를 활용하지만, 원한다면 자신만의 디자인 토큰이나 유틸리티 클래스로 교체해 사용할 수 있습니다.
Radix UI Primitives
"unstyled, accessible, open source React primitives"로 불리는 저수진 UI 컴포넌트 모음
시각적 스타일을 제공하지 않고 접근성과 동작 로직을 지원
shadcn/ui는 실제 컴포넌트 코드를 제공합니다. 컴포넌트를 필요에 맞게 커스터마이징하고 확장할 수 있는 완전한 제어권을 갖게 됩니다.
일반적인 라이브러리에서는 버튼의 동작을 변경해야 할 경우 스타일을 오버라이드하거나 컴포넌트를 래핑해야 합니다.
shadcn/ui의 모든 컴포넌트는 공통된 컴포저블 인터페이스를 공유합니다. 컴포넌트가 존재하지 않는 경우, 가져와서 컴포저블하게 만들고 스타일을 조정하여 디자인 시스템의 나머지 부분과 일치하고 함께 작동하도록 합니다.
공유된 컴포저블 인터페이스는 팀과 LLM 모두에게 예측 가능함을 의미합니다. 모든 새로운 컴포넌트마다 다른 API를 배울 필요가 없습니다.
shadcn/ui는 코드 배포 시스템이기도 합니다. 컴포넌트의 스키마와 이를 배포하기 위한 CLI를 정의합니다.
스키마를 사용하여 컴포넌트를 다른 프로젝트에 배포하거나 AI가 기존 스키마를 기반으로 완전히 새로운 컴포넌트를 생성하도록 할 수 있습니다.
shadcn/ui는 신중하게 선택된 기본 스타일을 가진 많은 컴포넌트를 제공합니다. 이들은 독립적으로 보기 좋고 일관된 시스템으로 함께 잘 작동하도록 설계되었습니다.
UI 세계에서 "헤드리스(headless)"란 로직·상태·접근성(ARIA 등) 처리와 시각적 스타일링을 분리하는 개념을 뜻합니다.
<Dropdown>
이나 <Dialog>
의 동작만 가져와서 직접 레이아웃·CSS·클래스로 화면에 어떻게 보여질지 완전히 자유롭게 설계할 수 있습니다.bun create vite@latest
bun add tailwindcss @tailwindcss/vite
@import "tailwindcss";
Vite로 React+TypeScript 프로젝트를 셋업할 때, @/…
같은 경로 별칭(path alias) 을 사용하면 훨씬 깔끔하게 임포트할 수 있습니다.
tsconfig.json
수정// tsconfig.json
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
],
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"] // "@/components/Button" → "./src/components/Button"
}
}
}
tsconfig.app.json
에도 같은 내용 추가// tsconfig.app.json
{
"compilerOptions": {
// …다른 설정…
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
// …다른 설정…
}
}
vite.config.ts
)// vite.config.ts
import path from "path"
import react from "@vitejs/plugin-react"
import tailwindcss from "@tailwindcss/vite"
import { defineConfig } from "vite"
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: {
alias: {
"@": path.resolve(__dirname, "./src"),
},
},
})
@types/node
설치 (옵션)pnpm add -D @types/node
bunx --bun shadcn@latest init
bunx --bun shadcn@latest add button
shadcn/ui를 사용하면:
"헤드리스"의 핵심은 동작(behavior) 과 표현(presentation) 을 분리하는 것이며, shadcn/ui의 철학을 따르면 유연하면서도 유지 보수하기 쉬운 UI 시스템을 구축할 수 있습니다.
기존 컴포넌트 라이브러리 접근 방식에서 벗어나, 개발자에게 컴포넌트의 완전한 제어권을 제공하는 shadcn/ui는 현대적인 웹 개발에서 새로운 대안을 제시합니다.