MENU
Wwoon

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 dialog

Toast를 추가하려면:

pnpm dlx @woon-ui/cli add toast

여러 개를 한 번에 추가할 수도 있습니다.

pnpm dlx @woon-ui/cli add dialog toast popover

Note

Woon의 공개 패키지는 모두 react >= 19.0.0react-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.ts

dialog.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/toast

CSS는 앱 진입점에서 직접 import합니다.

import '@woon-ui/dialog/css'
import '@woon-ui/toast/css'

한 개의 dependency와 한 개의 CSS entry가 더 편하다면 @woon-ui/react 번들도 계속 사용할 수 있습니다.

npm install @woon-ui/react
import '@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하던 흐름에서 옮긴다면, 이제는 다음 둘 중 하나를 선택하면 됩니다.

  1. pnpm dlx @woon-ui/cli add ...로 configured UI path에 local scaffold를 생성한다.
  2. 기능 패키지를 직접 설치하고 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" />
    </>
  )
}