14. 설치와 구조
init에서 고르는 것 중 셋은 나중에 못 바꾼다
처음부터 끝까지
섹션 제목: “처음부터 끝까지”-
Next.js 프로젝트
터미널 창 pnpm create next-app@latest my-appcd my-app -
shadcn/ui 초기화
터미널 창 pnpm dlx shadcn@latest init -
첫 컴포넌트
터미널 창 pnpm dlx shadcn@latest add button -
쓴다
app/page.tsx import { Button } from '@/components/ui/button'export default function Home() {return <Button>클릭</Button>}
전제 조건 두 가지: Tailwind가 설치돼 있을 것,
tsconfig.json에 @/* alias가 있을 것. create-next-app이 둘 다 해준다.
init이 하는 일
섹션 제목: “init이 하는 일”components.json생성 — 이후 모든 CLI 동작의 기준이 된다lib/utils.ts생성 —cn()함수 (11장)globals.css수정 — 토큰(:root,.dark)과@theme inline블록 추가- 의존성 설치 —
clsx,tailwind-merge,class-variance-authority, 프리미티브 - 아이콘 라이브러리 설치 — 기본은 lucide
3번이 12장에서 본 그 토큰 블록이다.
init 직후 globals.css를 열어보면 학습 효과가 크다.
components.json
섹션 제목: “components.json”{ "$schema": "https://ui.shadcn.com/schema.json", "style": "new-york", "rsc": true, "tsx": true, "tailwind": { "config": "", "css": "app/globals.css", "baseColor": "zinc", "cssVariables": true, "prefix": "" }, "aliases": { "components": "@/components", "ui": "@/components/ui", "utils": "@/lib/utils", "lib": "@/lib", "hooks": "@/hooks" }, "registries": {}}| 필드 | 의미 | 나중에 바꿀 수 있나 |
|---|---|---|
style | 컴포넌트의 시각적 성격 | 불가 |
rsc | true면 필요한 파일에 use client 자동 추가 | 가능 |
tsx | false면 .jsx로 생성 | 가능 |
tailwind.config | v4에서는 빈 문자열 | — |
tailwind.css | 토큰을 주입할 CSS 파일 경로 | 가능 |
tailwind.baseColor | 중립색 계열 | 불가 |
tailwind.cssVariables | true면 의미 토큰, false면 유틸리티 직접 | 불가 |
tailwind.prefix | 유틸리티 접두사 (tw- 등) | 가능 |
aliases.* | 파일이 놓일 위치 | 가능 |
registries | 외부 레지스트리 등록 | 가능 |
되돌릴 수 없는 세 가지
섹션 제목: “되돌릴 수 없는 세 가지”cssVariables를 반드시 true로
섹션 제목: “cssVariables를 반드시 true로”이 선택이 이 덱 전체에서 가장 중요한 설정 하나다.
<div className="bg-background text-foreground">- 다크 모드가 공짜 (12장)
- 테마 교체가 변수 몇 줄 (17장)
- 컴포넌트에 원시 색이 없다
<div className="bg-white text-zinc-950 dark:bg-zinc-950 dark:text-zinc-50">- 모든 컴포넌트에
dark:변형이 붙는다 - 테마 교체 = 전 파일 수정
- 17장의 작업이 사실상 불가능해진다
baseColor — 중립색 고르기
섹션 제목: “baseColor — 중립색 고르기”앱의 90%를 차지하는 회색 계열이다. 미묘하지만 인상 차이가 크다.
| 계열 | 성격 |
|---|---|
zinc | 완전 중립. 가장 무난하다 |
slate | 푸른 기. 차분하고 테크틱 |
stone | 따뜻한 기. 부드러움 |
neutral | 순수 무채색 |
mauve / olive / mist / taupe | 미세한 색조가 섞인 중립색 |
zinc — 완전 중립 · 가장 무난
50
100
200
300
400
500
600
700
800
900
950
slate — 푸른 기 · 차분하고 테크틱
50
100
200
300
400
500
600
700
800
900
950
stone — 따뜻한 기 · 부드러움
50
100
200
300
400
500
600
700
800
900
950
브랜드 색이 따뜻하면 stone/taupe, 차가우면 zinc/mist 쪽이 어울린다.
style — 여덟 가지 시각적 성격
섹션 제목: “style — 여덟 가지 시각적 성격”예전에는 default와 new-york 둘뿐이었다. 지금은 여덟 가지다.
| 스타일 | 성격 |
|---|---|
vega / nova | 예전 new-york 계열. 조밀하고 그림자 위주 |
maia / lyra / mira | 코어 라인업 |
luma | 2026년 3월 추가 |
rhea | luma를 더 조밀하게. 밀도 높은 제품 화면용 |
sera | 타이포 중심. 세리프 제목 + 각진 모서리 + 밑줄 컨트롤 |
--style 플래그나 shadcn/create에서 고른다.
나중에 못 바꾸므로 프로젝트 시작 전에 웹사이트에서 실물을 비교해 보는 게 좋다.
CLI 다루기
섹션 제목: “CLI 다루기”| 명령 | 하는 일 |
|---|---|
init / create | 프로젝트 설정 · 새 프로젝트 생성 |
add [name…] | 컴포넌트 추가 |
view [name…] | 설치 전에 소스를 미리 본다 |
search / list | 레지스트리에서 검색·목록 |
docs [name] | 컴포넌트 문서·API 조회 |
info | 현재 프로젝트 설정 확인 |
build | registry.json → 배포용 JSON 생성 (16장) |
migrate | 아이콘 교체, RTL, radix 통합 패키지 전환 |
apply / preset | 프리셋(테마 등) 적용 (17장) |
eject | shadcn 유틸을 인라인화하고 의존성 제거 (되돌릴 수 없음) |
알아두면 좋은 플래그
섹션 제목: “알아두면 좋은 플래그”# 설치 전에 소스 확인pnpm dlx shadcn@latest view button
# 무엇이 바뀔지만 보고 실행 안 함pnpm dlx shadcn@latest add dialog --dry-run
# 내가 수정한 파일과 최신 버전의 차이pnpm dlx shadcn@latest add button --diff
# 수정본을 덮어쓰기 (주의)pnpm dlx shadcn@latest add button --overwrite
# 전부 설치pnpm dlx shadcn@latest add --all
# 특정 경로에pnpm dlx shadcn@latest add card --path components/shared의존성이 자동으로 따라온다
섹션 제목: “의존성이 자동으로 따라온다”pnpm dlx shadcn@latest add dialog✔ Created 3 files: - components/ui/dialog.tsx - components/ui/button.tsx ← dialog가 필요로 해서 - hooks/use-media-query.ts ← 함께✔ Installed 1 package: - @base-ui-components/reactregistryDependencies가 다른 레지스트리 항목을 가리킨다dependencies는 npm 패키지를 가리킨다- 이미 있는 파일은 덮어쓰지 않는다 (
--overwrite없이는)
설치 후 파일 지도
섹션 제목: “설치 후 파일 지도”- components.json CLI의 기준. git에 커밋한다
디렉터리app/
- globals.css 토큰. 여기가 디자인 시스템의 뿌리
디렉터리lib/
- utils.ts
cn()
- utils.ts
디렉터리components/
디렉터리ui/ shadcn이 관리하는 영역
- button.tsx
- card.tsx
- dialog.tsx
이 네 가지가 앞으로 계속 나온다.
특히 globals.css와 components/ui/가 이 스택의 자산이 쌓이는 곳이다.
모노레포에서
섹션 제목: “모노레포에서”pnpm dlx shadcn@latest init --monorepo디렉터리apps/
디렉터리web/
- components.json →
"ui": "@workspace/ui/components"
- components.json →
디렉터리admin/
- components.json
디렉터리packages/
디렉터리ui/
- components.json 컴포넌트가 실제로 사는 곳
디렉터리src/components/
- …
- src/styles/globals.css 토큰도 여기
- 컴포넌트와 토큰은
packages/ui한 곳에만 둔다 - 각 앱은 그걸 import만 한다
add를 앱에서 실행해도 파일은packages/ui에 생긴다
14장 요약
섹션 제목: “14장 요약”init은 components.json · lib/utils.ts · globals.css 토큰 · 의존성을 만든다cssVariables: true는 반드시 켠다. 나중에 못 바꾸고, 테마 교체가 불가능해진다style과baseColor도 나중에 못 바꾼다 — 시작 전에 실물을 비교한다- 기본 베이스는 Base UI,
-b radix로 Radix 선택 가능 view(미리보기),--dry-run,--diff(수정 추적)를 기억한다- 모노레포는
packages/ui에 컴포넌트와 토큰을 모은다
15. 컴포넌트 해부button.tsx를 한 줄씩 — 소유한다는 것은 읽을 수 있다는 뜻이다.