Getting Started
Installation
기능별 패키지 설치, runtime mount, CSS import, migration 포인트까지 프로젝트에 Woon을 추가하는 방법을 안내합니다.
CLI 설치 권장
지금 권장하는 시작 방식은 pnpm dlx @woon-ui/cli입니다.
CLI는 필요한 패키지를 설치하고, 프로젝트 안의 configured UI path 아래에 로컬 UI 파일을 생성합니다. 즉 Woon의 behavior는 패키지에서 가져오고, 앱에서 직접 소유할 UI wrapper는 로컬 파일로 관리하는 방식입니다.
Dialog를 추가하려면:
pnpm dlx @woon-ui/cli add dialogToast를 추가하려면:
pnpm dlx @woon-ui/cli add toast여러 개를 한 번에 추가할 수도 있습니다.
pnpm dlx @woon-ui/cli add dialog toast popoverNote
Woon의 공개 패키지는 모두 react >= 19.0.0과 react-dom >= 19.0.0을 peer dependency로 요구합니다.
init과 woon.json
init 명령은 존재하지만, 먼저 꼭 실행할 필요는 없습니다.
처음 add를 실행할 때 woon.json이 없으면 CLI가 자동으로 생성합니다.
pnpm dlx @woon-ui/cli init이 파일에는 framework, package manager, 그리고 local scaffold 경로가 저장됩니다.
{
"$schema": "https://woon-ui.dev/schema.json",
"framework": "next-app-router",
"packageManager": "pnpm",
"paths": {
"ui": "src/woon/ui",
"hooks": "src/woon/hooks",
"lib": "src/woon/lib"
},
"aliases": {
"ui": "@/woon/ui",
"hooks": "@/woon/hooks",
"lib": "@/woon/lib"
},
"style": "colocated-css"
}CLI는 이후 add 명령에서 이 설정을 읽어 같은 위치에 파일을 계속 생성합니다.
생성되는 파일
예를 들어 pnpm dlx @woon-ui/cli add dialog를 실행하면 대략 이런 구조가 생깁니다.
src/
woon/
ui/
dialog.tsx
dialog.css
index.tsdialog.tsx는 앱이 직접 소유하는 local wrapper입니다.
dialog.css는 이 wrapper 옆에 colocate된 CSS 파일이며, 기본적으로 패키지 CSS를 가져온 뒤 필요한 override를 추가하는 구조입니다.
import './dialog.css'
import { Dialog as DialogPrimitive, useWoonDialogContext } from '@woon-ui/dialog'@import '@woon-ui/dialog/css';
/* Add local overrides here. */이 방식의 장점은 다음과 같습니다.
- generated file이 configured UI path 아래에 모여서 shadcn처럼 관리된다
- CSS import 위치가 컴포넌트 옆에 있어 수정 지점이 분명하다
- 패키지 API는 그대로 쓰되, 앱 고유 UI는 언제든 로컬에서 분기할 수 있다
CLI 출력
기본 출력은 파일 생성 결과와 다음 단계만 짧게 안내합니다.
runtime 전체 스니펫은 기본적으로 숨기고, 필요할 때만 --verbose로 출력합니다.
pnpm dlx @woon-ui/cli add dialog toast --verbose기본 출력은 이런 식입니다.
Added dialog, toast
Local UI path: src/woon/ui
Created:
- woon.json
- src/woon/ui/dialog.tsx
- src/woon/ui/dialog.css
- src/woon/ui/toast.tsx
- src/woon/ui/toast.css
Updated:
- src/woon/ui/index.ts
Next step:
- Mount DialogRuntime once in src/app/layout.tsx
- Mount Toaster with Toast from '@/woon/ui/toast' once in src/app/layout.tsx
Docs:
- https://woon-ui.vercel.app/docs/installation
- https://woon-ui.vercel.app/docs/components/dialog
- https://woon-ui.vercel.app/docs/components/toast즉 CLI는 다음 단계와 문서 링크만 먼저 보여주고, 실제 코드 블록이 필요할 때만 --verbose로 자세한 runtime snippet을 확인하는 방식입니다.
Runtime Mount
CLI는 DialogRuntime이나 Toaster를 자동으로 앱 루트에 삽입하지 않습니다.
이 연결은 사용자가 직접 명시하는 쪽이 더 명확합니다.
Dialog 계열 API를 쓴다면 앱 루트에 DialogRuntime을 한 번 mount하세요.
import { DialogRuntime } from '@woon-ui/dialog'
export function AppRoot() {
return (
<>
<App />
<DialogRuntime />
</>
)
}Toast를 쓴다면 Toaster를 한 번 mount하세요.
import { Toaster } from '@woon-ui/toast'
import { Toast } from '@/woon/ui/toast' // or your configured ui path
export function AppRoot() {
return (
<>
<App />
<Toaster position="bottom-right" render={Toast} />
</>
)
}useDialog(), alert(), confirm()에는 DialogRuntime이 필요하고,
toast()에는 Toaster가 필요합니다.
Tip
앱 루트 연결 예시는 Runtime Setup 문서를 참고하세요. CLI가 코드 블록까지 출력하길 원하면 --verbose를 사용하세요.
Manual Install
CLI 없이 기능 패키지를 직접 설치해서 써도 됩니다. local UI scaffold가 필요 없거나, 기존 구조에 직접 연결하고 싶다면 이 방식을 사용하세요.
Dialog와 Toast를 함께 쓴다면:
npm install @woon-ui/dialog @woon-ui/toastCSS는 앱 진입점에서 직접 import합니다.
import '@woon-ui/dialog/css'
import '@woon-ui/toast/css'한 개의 dependency와 한 개의 CSS entry가 더 편하다면 @woon-ui/react 번들도 계속 사용할 수 있습니다.
npm install @woon-ui/reactimport '@woon-ui/react/css'새 문서와 예제는 CLI 또는 기능별 패키지 설치를 기준으로 설명합니다.
@woon-ui/react는 convenience layer로 이해하면 됩니다.
TypeScript
Woon의 공개 패키지는 TypeScript로 작성되어 타입 정의가 내장되어 있습니다.
별도의 @types 패키지가 필요하지 않습니다.
React 19의 기능을 사용하므로, tsconfig.json에서 React 타입이 19 이상인지 확인하세요.
{
"compilerOptions": {
"jsx": "react-jsx"
}
}Migration
이전 문서처럼 복사형 예제만 보고 직접 wiring하던 흐름에서 옮긴다면, 이제는 다음 둘 중 하나를 선택하면 됩니다.
pnpm dlx @woon-ui/cli add ...로 configured UI path에 local scaffold를 생성한다.- 기능 패키지를 직접 설치하고 runtime/CSS를 수동으로 연결한다.
어느 방식을 쓰더라도 runtime mount는 여전히 명시적으로 연결합니다.
import { DialogRuntime } from '@woon-ui/dialog'
import { Toaster } from '@woon-ui/toast'
export function AppRoot() {
return (
<>
<App />
<DialogRuntime />
<Toaster position="bottom-right" />
</>
)
}