웹 개발자에게 완벽한 UI 툴킷을 찾는 것은 끊임없는 노력입니다. 수년 동안 React 개발자들은 Material-UI (MUI), Ant Design, Chakra UI와 같은 전통적인 컴포넌트 라이브러리에 의존해 왔습니다. 이러한 라이브러리는 풍부한 사전 구축 컴포넌트를 제공하여 개발 속도를 높여줄 것을 약속합니다. 하지만 종종 제어력 부족, 스타일 오버라이드 시 발생하는 어려움, 그리고 번들 크기 증가라는 단점을 수반합니다.
여기 Shadcn UI가 등장했습니다. React 커뮤니티를 강타한 패러다임 전환적인 접근 방식입니다. 여러분이 익숙한 방식의 컴포넌트 라이브러리가 아닙니다. 그보다 더 나은 것입니다. 아름답게 디자인되고 접근성이 뛰어나며 끝없이 재사용 가능한 컴포넌트 모음으로, npm에서 종속성으로 설치하는 것이 아니라 프로젝트에 직접 복사해서 사용합니다.
이 포괄적인 4000단어 튜토리얼은 여러분을 완전한 초보자에서 자신감 있는 Shadcn UI 실무자로 안내하는 확실한 가이드가 될 것입니다. 우리는 그 근본 철학을 탐구하고, 상세한 설정 과정을 거치며, 복잡한 UI를 구축하고, 고급 테마 및 폼 핸들링을 마스터하며, 대규모 애플리케이션을 위한 모범 사례를 논의할 것입니다. UI 툴킷에 대해 기대하는 바를 다시 생각할 준비를 하십시오.
개발 팀이 최대 생산성으로 함께 작업할 수 있는 통합된 올인원 플랫폼을 원하십니까?
Apidog는 여러분의 모든 요구 사항을 충족하며, Postman을 훨씬 저렴한 가격으로 대체합니다!
Shadcn UI 철학 - 새로운 구축 방식
코드를 한 줄도 작성하기 전에 Shadcn UI가 왜 존재하고 어떤 문제를 해결하는지 이해하는 것이 가장 중요합니다. 이 핵심 철학을 파악하는 것이 그 잠재력을 완전히 발휘하는 열쇠입니다.
Shadcn UI가 아닌 것
- 전통적인 npm 패키지가 아닙니다.
package.json
의 종속성 목록에서shadcn-ui
를 찾을 수 없습니다. 이것이 가장 중요한 차이점입니다. - 모놀리식 라이브러리가 아닙니다. 버튼과 입력 필드만 필요한데 수백 개의 컴포넌트를 설치하도록 강요하지 않습니다.
- 제한적이지 않습니다. 특정 디자인 미학에 갇히거나 라이브러리 유지보수자가 제공하는 테마 기능에 제한되지 않습니다.
Shadcn UI인 것
- 재사용 가능한 코드 모음: 전문가가 엄선한 레시피 세트라고 생각하십시오. 원하는 레시피(예:
Card
컴포넌트)를 선택하면, 자신의 주방(프로젝트)에서 요리할 수 있도록 지침(코드)이 제공됩니다. - 코드 소유권에 대한 약속: Shadcn 컴포넌트를 추가하면 해당 소스 코드(
.tsx
파일)가 일반적으로components/ui/
아래에 있는 코드베이스에 직접 배치됩니다. 이제 그것은 여러분의 컴포넌트입니다. 구조, 스타일, 로직 등 무엇이든 변경할 수 있습니다. 이는 간단한 시각적 조정을 위해!important
CSS 오버라이드나 복잡한 prop API와 씨름하는 답답한 경험을 없애줍니다. - 현대적이고 견고한 기반 위에 구축: Shadcn UI는 바퀴를 재발명하지 않습니다. 거인의 어깨 위에 서 있습니다.
- Tailwind CSS: 마크업에서 직접 어떤 디자인이든 생성하기 위한 저수준 빌딩 블록을 제공하는 유틸리티 우선 CSS 프레임워크입니다. Shadcn 컴포넌트는 Tailwind로만 스타일이 지정되어 있어, 이 프레임워크에 익숙하다면 놀라울 정도로 쉽게 사용자 정의할 수 있습니다.
- Radix UI: 스타일이 지정되지 않은 접근성 있는 저수준 UI 프리미티브 라이브러리입니다. Radix는 키보드 탐색, 포커스 관리, 접근성을 위한 ARIA 속성(a11y) 등 UI 컴포넌트의 복잡하고 종종 간과되는 모든 측면을 처리합니다. Shadcn은 이러한 강력한 헤드리스 프리미티브를 가져와 Tailwind CSS로 아름다운 스타일을 추가합니다.
이 모델의 주요 장점은 속도와 제어력의 융합입니다. 사전 구축된 컴포넌트를 사용하여 초기 속도를 얻으면서도 코드 소유에서 오는 장기적인 유연성과 유지보수성을 희생하지 않습니다.
무대 설정 - 프로젝트 설정 및 설치
이론에서 실습으로 전환해 봅시다. 처음부터 새 프로젝트를 설정할 것입니다. 이 가이드에서는 주로 Next.js를 사용할 것입니다. 서버 컴포넌트와 파일 기반 라우팅이 Shadcn UI의 정신과 완벽하게 일치하기 때문입니다. Vite 설정도 간략하게 다룰 것입니다.
1단계: 환경 필수 조건
개발 환경이 준비되었는지 확인하십시오. 다음이 필요합니다.
- Node.js: 최신 LTS(Long-Term Support) 버전을 권장합니다. 공식 Node.js 웹사이트에서 다운로드할 수 있습니다.
- 패키지 관리자: 이 튜토리얼에서는 Node.js에 번들로 제공되는
npm
을 사용할 것입니다.yarn
또는pnpm
도 사용할 수 있습니다.
2단계: 새 Next.js 애플리케이션 생성
터미널을 열고 다음 명령을 실행하여 새 Next.js 프로젝트를 부트스트랩합니다.Bash
npx create-next-app@latest my-pro-shadcn-app --typescript --tailwind --eslint
이 명령은 my-pro-shadcn-app
이라는 디렉토리에 새 애플리케이션을 스캐폴딩합니다. 몇 가지 중요한 플래그를 포함했습니다.
--typescript
: Shadcn UI는 TypeScript로 작성되었으며 TypeScript 환경에서 가장 잘 작동합니다.--tailwind
: Tailwind CSS는 Shadcn UI 스타일링의 필수 종속성입니다.--eslint
: 코드 품질 유지를 위한 좋은 습관입니다.
설치 프로그램이 몇 가지 질문을 할 것입니다. 다음은 최신 Next.js 14+ 설정에 권장되는 선택 사항입니다.
✔ `src/` 디렉토리를 사용하시겠습니까? … No / **Yes**
✔ App Router를 사용하시겠습니까? (권장) … No / **Yes**
✔ 기본 가져오기 별칭을 사용자 정의하시겠습니까? … **No** / Yes
App Router를 사용하는 것은 표준 관행이며, src/
디렉토리는 코드 구성에 도움이 됩니다. 완료되면 새 프로젝트로 이동하십시오.Bash
cd my-pro-shadcn-app
3단계: init
명령 - Shadcn UI 활성화
이것이 가장 중요한 단계입니다. Shadcn UI는 프로젝트를 구성하기 위한 CLI 도구를 제공합니다. 프로젝트의 루트 디렉토리에서 다음 명령을 실행하십시오.Bash
npx shadcn-ui@latest init
이렇게 하면 프로젝트 설정을 위한 대화형 설문이 시작됩니다. 각 질문과 그 중요성을 살펴보겠습니다.
- TypeScript를 사용하시겠습니까 (권장)?
Yes
. 우리는 TypeScript 프로젝트에 있습니다. - 어떤 스타일을 사용하시겠습니까?
Default
vs.New York
. 두 가지 미리 정의된 시각적 스타일입니다.Default
는 약간 더 넓고,New York
은 더 간결합니다. Shadcn UI 웹사이트에서 예시를 볼 수 있습니다. 여기서는Default
를 선택하겠습니다. - 기본 색상으로 어떤 색상을 사용하시겠습니까? 이는 UI의 기본 색상 팔레트를 설정합니다. 기본값은
Slate
입니다. 지금은Slate
를 그대로 사용하겠습니다. 나중에 변경하는 방법을 배울 것입니다. global.css
파일은 어디에 있습니까? CLI는src/app/globals.css
에서 이를 올바르게 감지합니다. 이 파일은 테마 설정을 위한 핵심 CSS 변수가 주입될 곳입니다.- 테마 설정을 위해 CSS 변수를 사용하시겠습니까?
Yes
. 이는 Shadcn 테마 시스템의 핵심이며, 동적 변경(예: 다크/라이트 모드)과 쉬운 사용자 정의를 가능하게 합니다. tailwind.config.ts
는 어디에 위치합니까? CLI는src/tailwind.config.ts
를 감지합니다. 이 파일은 Shadcn의 테마 프리셋을 통합하기 위해 수정될 것입니다.- 컴포넌트 가져오기 별칭을 구성하십시오:
@/components
. 이것은 모범 사례입니다. 파일이 아무리 깊게 중첩되어 있더라도import { Button } from "@/components/ui/button";
와 같이 깔끔한 경로로 컴포넌트를 항상 가져올 수 있음을 의미합니다. - 유틸리티 가져오기 별칭을 구성하십시오:
@/lib/utils
. 위와 마찬가지로 유틸리티 함수에 대한 것입니다. - React Server Components를 사용하고 있습니까?
Yes
. 우리는 기본적으로 Server Components를 사용하는 App Router를 선택했습니다. components.json
에 구성을 작성하시겠습니까?Yes
. 이는 모든 선택 사항을 기억하는 중요한 파일을 생성하여npx shadcn-ui@latest add ...
를 실행할 때마다 이러한 질문에 답할 필요가 없도록 합니다.
확인 후 CLI는 마법을 부립니다.
- 종속성 설치:
tailwindcss-animate
및class-variance-authority
와 같은 필요한 패키지를 추가합니다. components.json
생성: 구성 선택 사항을 저장합니다.tailwind.config.ts
업데이트: Shadcn UI 플러그인 및 테마 구성이 주입됩니다.globals.css
업데이트: 전체 색상 팔레트, 테두리 반경 등을 정의하는 큰 CSS 변수 블록이 추가됩니다.lib/utils.ts
생성: 이 파일은 Tailwind CSS 클래스를 조건부로 병합하기 위한 영리한 유틸리티인cn
헬퍼 함수를 내보냅니다.
이제 프로젝트가 완전히 구성되었습니다.
(대안: Vite 설정)
Vite와 React를 사용하고 있다면 과정은 매우 유사합니다. Vite + React + TS 프로젝트를 설정한 후 Tailwind CSS를 수동으로 설치하고 npx shadcn-ui@latest init을 실행합니다. CLI는 Vite 설정을 감지할 만큼 똑똑하며 파일 위치(예: globals.css 대신 index.css)에 대해 약간 다른 질문을 할 것입니다.
UI 구축 - 간단한 컴포넌트에서 복잡한 레이아웃까지
설정이 완료되었으니 이제 구축을 시작해 봅시다. 핵심 워크플로우는 다음과 같습니다. 필요를 식별하고, 컴포넌트를 추가하고, 사용합니다.
4단계: 첫 번째 컴포넌트 추가 및 사용
기본 Next.js 보일러플레이트를 정리하고 간단한 인터페이스를 구축해 봅시다.
1. 버튼 추가:Bash
npx shadcn-ui@latest add button
어떤 일이 발생하는지 살펴보십시오. 새 파일 src/components/ui/button.tsx
가 생성됩니다. 이것이 여러분의 버튼입니다. 여러분이 소유합니다.
2. 카드 추가:Bash
npx shadcn-ui@latest add card
이 명령은 더 흥미롭습니다. src/components/ui/card.tsx
를 생성합니다. 이 파일을 검사하면 여러 컴포넌트를 내보내는 것을 볼 수 있습니다. Card
, CardHeader
, CardTitle
, CardDescription
, CardContent
, CardFooter
. 이는 복합 컴포넌트의 일반적인 패턴입니다.
3. UI 구축:
이제 src/app/page.tsx
를 열고 내용을 다음으로 바꿉니다.TypeScript
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { Input } from "@/components/ui/input"; // 다음으로 추가할 것입니다.
import { Label } from "@/components/ui/label"; // 그리고 이것도
export default function Home() {
return (
<main className="flex min-h-screen items-center justify-center bg-background p-8">
<Card className="w-full max-w-md">
<CardHeader>
<CardTitle className="text-2xl">프로젝트 생성</CardTitle>
<CardDescription>
한 번의 클릭으로 새 프로젝트를 배포하세요.
</CardDescription>
</CardHeader>
<CardContent className="grid gap-4">
<div className="grid gap-2">
<Label htmlFor="name">이름</Label>
<Input id="name" placeholder="프로젝트 이름" />
</div>
<div className="grid gap-2">
<Label htmlFor="framework">프레임워크</Label>
{/* 나중에 Select 컴포넌트로 바꿀 것입니다. */}
<Input id="framework" placeholder="예: Next.js" />
</div>
</CardContent>
<CardFooter>
<Button className="w-full">배포</Button>
</CardFooter>
</Card>
</main>
);
}
Input
및 Label
컴포넌트가 없으므로 코드가 아직 실행되지 않습니다. 추가해 봅시다.Bash
npx shadcn-ui@latest add input
npx shadcn-ui@latest add label
이제 개발 서버를 실행합니다.Bash
npm run dev
http://localhost:3000
으로 이동하십시오. 카드 안에 깔끔하고 전문적인 모양의 양식이 표시됩니다. w-full
, max-w-md
, grid
와 같은 유틸리티 클래스를 JSX에 직접 사용하여 레이아웃을 제어하는 방식을 주목하십시오. 이것이 Shadcn과 Tailwind CSS를 결합하는 힘입니다.
5단계: 더 정교한 컴포넌트 소개
정적 입력은 좋지만 실제 앱에는 대화형 요소가 필요합니다. 양식을 개선해 봅시다.
1. Select
컴포넌트 추가: "프레임워크" 입력은 드롭다운이어야 합니다. Select
컴포넌트를 추가해 봅시다. 이것은 더 복잡하며 다른 컴포넌트에 종속성이 있습니다.Bash
npx shadcn-ui@latest add select
CLI는 똑똑합니다. Select
가 작동하려면 Popover
컴포넌트가 필요하다는 것을 감지하고 해당 종속성도 설치할 권한을 요청할 것입니다. 이는 종속성을 수동으로 추적할 필요가 없도록 하는 환상적인 기능입니다.
2. Select
컴포넌트 통합: src/app/page.tsx
에서 "프레임워크"에 대한 Input
을 새 Select
컴포넌트로 바꿉니다.TypeScript
// 상단에 다음 import를 추가합니다.
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
// ... CardContent 내부
<div className="grid gap-2">
<Label htmlFor="framework">프레임워크</Label>
<Select>
<SelectTrigger id="framework">
<SelectValue placeholder="프레임워크 선택" />
</SelectTrigger>
<SelectContent>
<SelectItem value="nextjs">Next.js</SelectItem>
<SelectItem value="sveltekit">SvelteKit</SelectItem>
<SelectItem value="astro">Astro</SelectItem>
<SelectItem value="nuxt">Nuxt.js</SelectItem>
</SelectContent>
</Select>
</div>
브라우저를 새로 고치십시오. 이제 애니메이션과 적절한 키보드 탐색 기능을 갖춘 완벽하게 기능하고 접근성 있는 선택 드롭다운이 있습니다. 이 모든 것은 내부적으로 작동하는 Radix UI 덕분입니다.
3. Toast
로 사용자 피드백 추가: 사용자가 "배포"를 클릭하면 어떻게 될까요? 피드백을 제공해야 합니다. Toast
컴포넌트가 이에 완벽합니다.
먼저 추가하십시오.Bash
npx shadcn-ui@latest add toast
다음으로, 토스트를 사용하려면 앱의 어느 곳에서든 표시될 수 있도록 루트 레이아웃에 <Toaster />
컴포넌트를 추가해야 합니다. src/app/layout.tsx
를 열고 수정하십시오.TypeScript
import { Toaster } from "@/components/ui/toaster" // Toaster import
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<Toaster /> {/* 여기에 추가, body 닫기 바로 전 */}
</body>
</html>
)
}
이제 토스트를 트리거할 방법이 필요합니다. useToast
훅을 사용할 것입니다. src/app/page.tsx
를 클라이언트 컴포넌트로 만들고 버튼 클릭을 처리하도록 업데이트해 봅시다.TypeScript
'use client'; // <-- 파일 맨 위에 추가
// ... 다른 import
import { useToast } from "@/components/ui/use-toast";
export default function Home() {
const { toast } = useToast(); // 훅에서 toast 함수 가져오기
function handleDeploy() {
toast({
title: "배포 예약 완료!",
description: "프로젝트 '프로젝트 이름'이 배포 중입니다.",
duration: 5000,
});
}
return (
<main className="flex min-h-screen items-center justify-center bg-background p-8">
<Card className="w-full max-w-md">
{/* ... CardHeader 및 CardContent ... */}
<CardFooter>
<Button className="w-full" onClick={handleDeploy}> {/* onClick 핸들러 추가 */}
배포
</Button>
</CardFooter>
</Card>
</main>
);
}
이제 "배포" 버튼을 클릭하면 화면 모서리에 세련된 알림이 나타납니다.
유효성 검사를 통한 전문적인 양식 구축
대부분의 실제 애플리케이션은 클라이언트 측 유효성 검사를 포함한 강력한 양식 처리가 필요합니다. Shadcn UI로 이를 처리하는 공식적인 방법은 상태 관리를 위해 react-hook-form
과 스키마 유효성 검사를 위해 zod
를 결합하는 것입니다. 구축해 봅시다.
6단계: 양식 종속성 설치
먼저 필요한 라이브러리를 설치해 봅시다.Bash
npm install react-hook-form zod @hookform/resolvers
react-hook-form
: 성능이 뛰어나고 유연하며 확장 가능한 양식 라이브러리입니다.zod
: TypeScript 우선 스키마 선언 및 유효성 검사 라이브러리입니다.@hookform/resolvers
:react-hook-form
이 유효성 검사를 위해zod
를 사용할 수 있도록 하는 브리지 라이브러리입니다.
7단계: Shadcn Form
컴포넌트 추가
Shadcn UI는 react-hook-form
을 UI 컴포넌트와 원활하게 연결하는 래퍼 역할을 하는 특수 Form
컴포넌트를 제공합니다.Bash
npx shadcn-ui@latest add form
이렇게 하면 src/components/ui/form.tsx
가 추가됩니다. 이 파일은 컨텍스트 인식 컴포넌트 세트(Form
, FormField
, FormItem
, FormLabel
, FormControl
, FormDescription
, FormMessage
)를 제공하여 보일러플레이트를 대폭 줄입니다.
8단계: 유효성 검사 스키마 생성
src/app/page.tsx
에서 zod
를 사용하여 양식 데이터의 모양과 규칙을 정의해 봅시다.TypeScript
// 상단에 다음 import를 추가합니다.
import { z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
이제 Home
컴포넌트 바로 위에 스키마를 생성해 봅시다.TypeScript
const formSchema = z.object({
projectName: z.string().min(2, {
message: "프로젝트 이름은 최소 2자 이상이어야 합니다.",
}).max(50, {
message: "프로젝트 이름은 50자를 초과할 수 없습니다.",
}),
framework: z.string({
required_error: "표시할 프레임워크를 선택하십시오.",
}),
});
이 스키마는 두 필드를 정의합니다. projectName
은 2자에서 50자 사이의 문자열이어야 하며, framework
는 필수 문자열입니다.
9단계: 양식 연결
이제 이러한 새로운 도구를 모두 사용하도록 Home
컴포넌트를 리팩토링해 봅시다.TypeScript
export default function Home() {
const { toast } = useToast();
// 1. 양식을 정의합니다.
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
projectName: "",
},
});
// 2. 제출 핸들러를 정의합니다.
function onSubmit(values: z.infer<typeof formSchema>) {
// 양식 값으로 무언가를 합니다.
// ✅ 이것은 타입 안전하고 유효성이 검사됩니다.
console.log(values);
toast({
title: "다음 값을 제출했습니다:",
description: (
<pre className="mt-2 w-[340px] rounded-md bg-slate-950 p-4">
<code className="text-white">{JSON.stringify(values, null, 2)}</code>
</pre>
),
});
}
// 3. Shadcn의 Form 컴포넌트로 JSX를 구축합니다.
return (
<main className="flex min-h-screen items-center justify-center bg-background p-8">
<Card className="w-full max-w-md">
<CardHeader>
<CardTitle className="text-2xl">프로젝트 생성</CardTitle>
<CardDescription>
한 번의 클릭으로 새 프로젝트를 배포하세요.
</CardDescription>
</CardHeader>
<CardContent>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="projectName"
render={({ field }) => (
<FormItem>
<FormLabel>이름</FormLabel>
<FormControl>
<Input placeholder="프로젝트 이름" {...field} />
</FormControl>
<FormDescription>
이것은 공개 표시 이름입니다.
</FormDescription>
<FormMessage /> {/* 유효성 검사 오류 표시 */}
</FormItem>
)}
/>
<FormField
control={form.control}
name="framework"
render={({ field }) => (
<FormItem>
<FormLabel>프레임워크</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder="프레임워크 선택" />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="nextjs">Next.js</SelectItem>
<SelectItem value="sveltekit">SvelteKit</SelectItem>
<SelectItem value="astro">Astro</SelectItem>
<SelectItem value="nuxt">Nuxt.js</SelectItem>
</SelectContent>
</Select>
<FormDescription>
배포하려는 프레임워크입니다.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" className="w-full">배포</Button>
</form>
</Form>
</CardContent>
</Card>
</main>
);
}
이것은 상당한 양의 코드이지만, 믿을 수 없을 정도로 강력하고 확장 가능한 패턴입니다. FormField
컴포넌트는 모든 상태 연결을 처리하며, FormMessage
는 사용자가 필드와 상호 작용할 때 zod
스키마에서 올바른 유효성 검사 오류를 자동으로 표시합니다. 빈 프로젝트 이름으로 양식을 제출하여 유효성 검사가 작동하는 것을 확인해 보십시오.
테마 및 사용자 정의 마스터하기
Shadcn UI의 진정한 힘은 자신만의 것으로 만들기 시작할 때 발휘됩니다.
10단계: CSS 변수를 사용한 고급 테마 설정
전체 테마는 src/app/globals.css
의 CSS 변수에 의해 정의됩니다. 이 파일을 열고 :root
및 .dark
블록을 찾으십시오.CSS
/* globals.css 예시 */
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
/* ... 그리고 더 많은 것 */
--radius: 0.5rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
--primary: 210 40% 98%;
--primary-foreground: 222.2 47.4% 11.2%;
/* ... */
}
- 색상 변경: 값은
hsl()
래퍼 없이 HSL(색조, 채도, 밝기) 값으로 표현됩니다. 이는 더 쉬운 조작을 위한 의도적인 선택입니다. 기본 브랜드 색상을 변경하려면 해당 색상의 HSL 값을 찾아--primary
및--primary-foreground
변수를 업데이트하기만 하면 됩니다. Shadcn UI Themes 페이지에는 색상을 선택하고 전체 테마 블록을 복사하여 붙여넣을 수 있는 환상적인 생성기가 있습니다. - 테두리 반경 변경: 더 날카로운 모서리를 원하십니까?
--radius: 0.5rem;
을--radius: 0.2rem;
또는 심지어0rem
으로 변경하십시오. 둥근 모서리가 있는 모든 컴포넌트는 이 변수를 사용하므로 변경 사항이 전역적으로 전파됩니다.
다크 모드 구현:
Shadcn은 .dark 클래스 블록과 tailwind.config.ts의 Tailwind의 darkMode: "class" 전략 덕분에 다크 모드를 위해 사전 구성되어 있습니다. 필요한 것은 <html> 요소에 dark 클래스를 토글하는 방법뿐입니다. 이를 위한 인기 있는 라이브러리는 next-themes입니다.
- 설치:
npm install next-themes
ThemeProvider
컴포넌트 생성 (src/components/theme-provider.tsx
): TypeScript
"use client"
import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes"
import { type ThemeProviderProps } from "next-themes/dist/types"
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
}
- 이 프로바이더로
RootLayout
래핑 (src/app/layout.tsx
): TypeScript
import { ThemeProvider } from "@/components/theme-provider"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
<Toaster />
</ThemeProvider>
</body>
</html>
)
}
- 마지막으로 토글 버튼 생성 (예:
src/components/mode-toggle.tsx
): TypeScript
"use client"
import * as React from "react"
import { Moon, Sun } from "lucide-react"
import { useTheme } from "next-themes"
import { Button } from "@/components/ui/button"
export function ModeToggle() {
const { theme, setTheme } = useTheme()
return (
<Button
variant="outline"
size="icon"
onClick={() => setTheme(theme === "light" ? "dark" : "light")}
>
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">테마 토글</span>
</Button>
)
}
이제 이 <ModeToggle />
을 앱의 어느 곳에든 배치하여 시스템 인식 및 사용자 재정의 가능한 다크 모드 토글을 얻을 수 있습니다.
11단계: 컴포넌트 소스 코드 사용자 정의
이것이 궁극적인 초능력입니다. 버튼에 녹색 배경을 가진 새로운 성공 변형을 원한다고 가정해 봅시다.
src/components/ui/button.tsx를 엽니다. buttonVariants 정의를 찾습니다. cva (Class Variance Authority)를 사용합니다. 단순히 새로운 변형을 추가합니다.TypeScript
const buttonVariants = cva(
// ... 기본 스타일
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
success: "bg-green-600 text-white hover:bg-green-600/90", // 우리의 새로운 변형
},
// ... 크기 변형
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
그게 다입니다. 이제 코드에서 사용할 수 있습니다. <Button variant="success">성공</Button>
. 복잡한 CSS 오버라이드를 작성할 필요가 없었습니다. 컴포넌트 자체의 소스 코드만 편집했습니다. 이 워크플로우는 간단하고 예측 가능하며 믿을 수 없을 정도로 강력합니다.
6부: 모범 사례 및 앞으로 나아갈 길
애플리케이션이 성장함에 따라 염두에 두어야 할 몇 가지 모범 사례가 있습니다.
- 파일 구성: CLI는 모든 것을
components/ui
에 넣지만, 이 폴더는 "기본" UI 키트로 간주되어야 합니다. 직접 구성하는 더 복잡한 컴포넌트(예: Shadcn의Card
,Avatar
,Button
을 사용하는UserProfileCard
)의 경우,components/shared
또는components/features
와 같은 다른 디렉토리에 생성하십시오. 이렇게 하면 기본 UI와 애플리케이션별 컴포넌트 사이에 명확한 구분이 유지됩니다. - 컴포넌트 업데이트: 원래 Shadcn UI 컴포넌트가 개선되면 어떻게 업데이트를 받을 수 있습니까? CLI가 해결해 줍니다.
npx shadcn-ui@latest add button
을 다시 실행할 수 있습니다. CLI는 이미button.tsx
파일이 있음을 감지하고diff
비교를 보여주어 파일을 덮어쓰거나 변경 사항을 수동으로 수락할 수 있도록 합니다. 컴포넌트의 미니 버전 관리와 같습니다. - 접근성 활용: Shadcn 컴포넌트는 Radix 프리미티브 위에 구축되었기 때문에 기본적으로 접근성이 있습니다. 이를 사용자 정의할 때 이 접근성을 깨뜨리지 않도록 주의하십시오. 예를 들어, 버튼의 색상을 변경하는 경우 텍스트에 충분한 대비가 있는지 확인하십시오. 새 컴포넌트를 구축할 때 Shadcn/Radix가 설정한 패턴을 따라 키보드 탐색 가능성 및 스크린 리더 지원을 유지하도록 노력하십시오.
결론: 여러분이 라이브러리 작성자입니다
이제 Shadcn UI의 핵심 철학부터 시작하여 고급 실제 패턴 구현까지 여정을 마쳤습니다. 그 진정한 혁신은 컴포넌트 자체뿐만 아니라 그것이 나타내는 패러다임 전환임을 보았습니다. 이는 개발자를 라이브러리의 단순한 소비자에서 자신만의 UI 툴킷의 큐레이터 및 소유자로 이동시킵니다.
원시 소스 코드를 제공하고, Tailwind CSS 및 Radix UI의 견고한 기반 위에 구축하며, 원활한 CLI 경험을 제공함으로써 Shadcn UI는 초기 개발 속도와 장기적인 유지보수성 및 창의적 자유 사이에서 완벽한 균형을 이룹니다. 더 이상 다른 사람의 디자인 시스템에 제약받지 않습니다. 프로젝트의 컴포넌트는 수정하고 확장하며 완벽하게 만들 수 있는 여러분 자신의 것입니다.
애플리케이션 UI의 미래는 더 이상 타사 종속성의 손에 달려 있지 않습니다. 바로 components
폴더에 있습니다. 즐거운 구축 되십시오.
개발 팀이 최대 생산성으로 함께 작업할 수 있는 통합된 올인원 플랫폼을 원하십니까?
Apidog는 여러분의 모든 요구 사항을 충족하며, Postman을 훨씬 저렴한 가격으로 대체합니다!