> ## Documentation Index
> Fetch the complete documentation index at: https://sonamu.cartanova.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# 설치하기

> Sonamu 설치 및 개발 환경 설정

Sonamu는 `create-sonamu` 패키지를 통해 프로젝트를 손쉽게 시작할 수 있습니다.

## 시스템 요구사항

Sonamu를 사용하기 위해서는 다음 환경이 필요합니다:

* **Node.js** v22 이상
* **pnpm** v10.23 이상
* **Docker** (데이터베이스 실행용)

<Tip>pnpm이 설치되지 않았다면 `corepack enable` 명령어로 활성화할 수 있습니다.</Tip>

<Frame caption="터미널에서 node --version, pnpm --version, docker --version 실행 결과">
  <img src="https://mintcdn.com/cartanova-7788888c/Ym6Y2Jrlq-5lmBML/images/installation1.png?fit=max&auto=format&n=Ym6Y2Jrlq-5lmBML&q=85&s=ecba1e0f34e775240351264a85a90a3a" alt="Node.js, pnpm, Docker 버전 확인" width="816" height="282" data-path="images/installation1.png" />
</Frame>

## 프로젝트 생성

터미널에서 다음 명령어를 실행하여 새 Sonamu 프로젝트를 생성합니다:

```bash theme={null}
pnpm create sonamu
```

### 인라인 옵션

프로젝트명을 인자로 전달하거나, 옵션을 통해 대화형 프롬프트를 건너뛸 수 있습니다:

```bash theme={null}
# 프로젝트명 직접 지정
pnpm create sonamu myapp

# 모든 옵션을 기본값으로 설정 (비대화형)
pnpm create sonamu myapp --yes

# pnpm/docker 설정 여부를 명시적으로 지정
pnpm create sonamu myapp --pnpm y --docker y

# pnpm만 자동 진행 (docker는 프롬프트로 물어봄)
pnpm create sonamu myapp --pnpm y

# docker만 자동 진행 (pnpm은 프롬프트로 물어봄, DB 옵션은 기본값)
pnpm create sonamu myapp --docker y

# 완전한 비대화형 모드 (모든 옵션 지정)
pnpm create sonamu myapp \
  --pnpm y \
  --docker y \
  --db-user=postgres \
  --db-password=1234 \
  --db-name=myapp \
  --container-name=myapp-pg \
  --docker-project=myapp-docker

# DB 옵션만 지정 (pnpm/docker 설정은 프롬프트로 물어봄)
pnpm create sonamu myapp --db-name myapp --db-password secret123
```

| 옵션                                     | 설명                                   | 기본값               |
| -------------------------------------- | ------------------------------------ | ----------------- |
| `--yes`, `-y`                          | 모든 옵션을 기본값으로 설정                      | -                 |
| `--pnpm`                               | pnpm 설치 여부 (`y`/`n`)                 | (프롬프트로 질문)        |
| `--docker`                             | Docker DB 설정 여부 (`y`/`n`)            | (프롬프트로 질문)        |
| `--skip-pnpm`                          | pnpm 설정 건너뛰기 (`--pnpm n`과 동일)        | false             |
| `--skip-docker`                        | Docker DB 설정 건너뛰기 (`--docker n`과 동일) | false             |
| `--docker-project`, `--docker-pj-name` | Docker Compose 프로젝트명                 | {프로젝트명}-docker    |
| `--db-user`                            | 데이터베이스 사용자명                          | postgres          |
| `--db-name`                            | 데이터베이스 이름                            | {프로젝트명}           |
| `--db-password`                        | 데이터베이스 비밀번호                          | 1234              |
| `--container-name`                     | Docker 컨테이너 이름                       | {프로젝트명}-container |

<Note>
  `--pnpm y`, `--docker y`에서 `y`는 `yes`, `true`, `1`로도 지정할 수 있습니다. 마찬가지로 `n`은
  `no`, `false`, `0`으로도 지정할 수 있습니다.
</Note>

<Frame caption="인라인 옵션 기본값으로 pnpm create sonamu 실행">
  <video muted loop playsInline controls className="w-full rounded-xl" preload="metadata" autoPlay src="https://mintcdn.com/cartanova-7788888c/mRzLpig-R41-Dqkz/images/installation2.mp4?fit=max&auto=format&n=mRzLpig-R41-Dqkz&q=85&s=f85fbce3a072ccea7e7a1d4280b49290" data-path="images/installation2.mp4" />
</Frame>

대화형 프롬프트가 나타나면 프로젝트 정보를 입력합니다:

```bash theme={null}
? Project name: myapp
? Would you like to set up pnpm? Yes
? Would you like to set up a database using Docker? Yes
? Enter the Docker project name: myapp-docker
? Enter the database user: postgres
? Enter the container name: myapp-container
? Enter the database name: myapp
? Enter the database password: ****
```

<Steps>
  <Step title="프로젝트명 입력">
    생성할 프로젝트의 이름을 입력합니다. 이 이름으로 디렉토리가 생성됩니다.

    <Warning>
      프로젝트명에는 **공백**과 \*\*하이픈(`-`)\*\*을 사용할 수 없습니다. 언더스코어(`_`)를 사용하세요.
    </Warning>
  </Step>

  <Step title="pnpm 설정">pnpm을 자동으로 설정할지 선택합니다. 권장 옵션입니다.</Step>

  <Step title="데이터베이스 설정">
    Docker를 사용한 PostgreSQL 데이터베이스를 설정할지 선택합니다. Yes를 선택하면:

    * Docker Compose 프로젝트명
    * 데이터베이스 사용자명
    * 컨테이너 이름
    * 데이터베이스 이름
    * 데이터베이스 비밀번호

    를 입력받고, 이 정보로 `packages/api/.env` 파일이 자동 생성됩니다.
  </Step>
</Steps>

<Frame caption="프로젝트 생성 완료 메시지 및 생성된 디렉토리 구조">
  <img src="https://mintcdn.com/cartanova-7788888c/mRzLpig-R41-Dqkz/images/installation3.png?fit=max&auto=format&n=mRzLpig-R41-Dqkz&q=85&s=e3df1917a9bf1494646a7d9295becafc" alt="프로젝트 생성 완료" width="1842" height="894" data-path="images/installation3.png" />
</Frame>

## 생성된 프로젝트 구조

`create-sonamu`는 다음과 같은 모노레포 구조를 생성합니다:

<Frame caption="VS Code에서 열린 프로젝트의 디렉토리 트리 구조">
  <img src="https://mintcdn.com/cartanova-7788888c/mRzLpig-R41-Dqkz/images/installation4.png?fit=max&auto=format&n=mRzLpig-R41-Dqkz&q=85&s=a522d9222fee5a0c0b39d5cb4232251b" alt="VS Code Explorer 사이드바" style={{ maxWidth: "500px", width: "100%", borderRadius: "0.75rem" }} width="1068" height="1972" data-path="images/installation4.png" />
</Frame>

<Tree>
  <Tree.Folder name="myapp" defaultOpen>
    <Tree.Folder name="packages" defaultOpen>
      <Tree.Folder name="api  (백엔드 API 서버)">
        <Tree.Folder name="src">
          <Tree.File name="index.ts  (서버 엔트리포인트)" />

          <Tree.File name="sonamu.config.ts  (Sonamu 설정)" />

          <Tree.Folder name="i18n  (다국어 설정)" />

          <Tree.Folder name="testing  (테스트 유틸리티)" />

          <Tree.Folder name="typings  (타입 정의)" />

          <Tree.Folder name="utils  (유틸리티 함수)" />
        </Tree.Folder>

        <Tree.Folder name="database">
          <Tree.File name="docker-compose.yml  (PostgreSQL 컨테이너)" />

          <Tree.Folder name="fixtures  (DB 초기화 스크립트)" />

          <Tree.Folder name="scripts  (dump, seed 스크립트)" />
        </Tree.Folder>

        <Tree.File name="package.json" />

        <Tree.File name="vitest.config.ts  (테스트 설정)" />

        <Tree.File name=".env  (환경변수, 자동 생성)" />
      </Tree.Folder>

      <Tree.Folder name="web  (프론트엔드 웹 앱)">
        <Tree.Folder name="src">
          <Tree.File name="entry-client.tsx  (클라이언트 엔트리포인트)" />

          <Tree.File name="App.tsx  (루트 컴포넌트)" />

          <Tree.Folder name="routes  (TanStack Router 기반 페이지)" />

          <Tree.Folder name="services  (API 서비스, 자동 생성)" />

          <Tree.Folder name="contexts  (React Context)" />

          <Tree.Folder name="i18n  (다국어 설정)" />

          <Tree.Folder name="admin-common  (공통 컴포넌트)" />
        </Tree.Folder>

        <Tree.File name="package.json" />

        <Tree.File name="vite.config.ts  (Vite 설정)" />

        <Tree.File name=".sonamu.env  (환경변수)" />
      </Tree.Folder>
    </Tree.Folder>

    <Tree.File name="pnpm-workspace.yaml  (워크스페이스 설정)" />

    <Tree.File name="README.md" />
  </Tree.Folder>
</Tree>

## 주요 설정 파일

### pnpm 워크스페이스

루트의 `pnpm-workspace.yaml`에서 모노레포 패키지와 공통 의존성 버전을 관리합니다:

```yaml title="pnpm-workspace.yaml" theme={null}
packages:
  - packages/api
  - packages/web

catalog:
  "@tanstack/react-query": ^5.90.12
  "@tanstack/react-router": 1.143.11
  react: ^19.2.3
  vite: 7.3.0
  vitest: 4.0.16
  # ... 기타 공통 의존성
```

### API 서버 엔트리포인트

생성된 API 서버의 진입점은 다음과 같습니다:

<Frame caption="VS Code에서 열린 packages/api/src/index.ts 파일">
  <img src="https://mintcdn.com/cartanova-7788888c/wk-O_9zBoKGthXNV/images/installation5.png?fit=max&auto=format&n=wk-O_9zBoKGthXNV&q=85&s=25761abe75f68e22157a5af4853478e4" alt="packages/api/src/index.ts 파일" style={{ maxWidth: "800px", width: "100%", borderRadius: "0.75rem" }} width="1446" height="576" data-path="images/installation5.png" />
</Frame>

### Sonamu 설정

`sonamu.config.ts`에서 프로젝트의 주요 설정을 관리합니다:

```typescript title="packages/api/src/sonamu.config.ts" theme={null}
import path from "node:path";
import { CachePresets, defineConfig } from "sonamu";
import { drivers as cacheDrivers, store } from "sonamu/cache";
import { drivers } from "sonamu/storage";

const host = "localhost";
const port = 34900;

export default defineConfig({
  projectName: process.env.PROJECT_NAME ?? "SonamuProject",
  api: {
    dir: "api",
    timezone: "Asia/Seoul",
    route: {
      prefix: "/api",
    },
  },
  i18n: {
    defaultLocale: "ko",
    supportedLocales: ["ko", "en"],
  },
  sync: {
    targets: ["web"],
  },
  database: {
    database: "pg",
    name: process.env.DATABASE_NAME ?? "database_name",
    defaultOptions: {
      connection: {
        host: process.env.DB_HOST || "0.0.0.0",
        port: Number(process.env.DB_PORT) || 5432,
        user: process.env.DB_USER || "postgres",
        password: process.env.DB_PASSWORD,
      },
    },
  },
  server: {
    listen: { port, host },
    // ... 서버, 스토리지, 캐시 설정
    cache: {
      default: "main",
      stores: {
        main: store().useL1Layer(cacheDrivers.memory({ maxSize: "50mb" })),
      },
      ttl: "5m",
    },
  },
});
```

### Docker Compose 설정

PostgreSQL 데이터베이스는 Docker로 관리됩니다:

```yaml title="packages/api/database/docker-compose.yml" theme={null}
version: "3.8"
name: ${CONTAINER_NAME}
services:
  pg:
    platform: linux/arm64
    image: pgvector/pgvector:pg18
    container_name: ${CONTAINER_NAME}
    env_file:
      - ../.env
    volumes:
      - ./fixtures/init.sh:/docker-entrypoint-initdb.d/init.sh
    environment:
      DATABASE_NAME: ${DATABASE_NAME}
      POSTGRES_DB: template1
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      TZ: Asia/Seoul
    ports:
      - "${DB_PORT}:5432"
```

### 프론트엔드 설정

Vite + React + TanStack Router + SSR 기반 애플리케이션이 생성됩니다:

```typescript title="packages/web/vite.config.ts" theme={null}
import tailwindcss from "@tailwindcss/vite";
import { tanstackRouter } from "@tanstack/router-plugin/vite";
import react from "@vitejs/plugin-react";
import dotenv from "dotenv";
import path from "path";
import Icons from "unplugin-icons/vite";
import { defineConfig } from "vite";

dotenv.config({ path: ".sonamu.env" });

export default defineConfig(({ command, isSsrBuild }) => ({
  plugins: [
    react(),
    Icons({ compiler: "jsx", jsx: "react", autoInstall: true }),
    tailwindcss(),
    tanstackRouter(),
  ],
  resolve: {
    alias: {
      "@": path.resolve(__dirname, "./src"),
    },
  },
  server: {
    host: "0.0.0.0",
    proxy: {
      "/api": `http://${process.env.API_HOST}:${process.env.API_PORT}`,
    },
  },
  // SSR 설정 포함
}));
```

## 포트 구성

기본 포트는 다음과 같이 설정됩니다:

| 서비스        | 포트    | 설명                                                                   |
| ---------- | ----- | -------------------------------------------------------------------- |
| API 서버     | 34900 | Fastify 기반 REST API                                                  |
| Sonamu UI  | -     | [http://localhost:34900/sonamu-ui](http://localhost:34900/sonamu-ui) |
| Web 앱      | 5173  | Vite 개발 서버 (Vite 기본값, SSR 지원)                                        |
| PostgreSQL | 5432  | 데이터베이스                                                               |

<Note>
  * **Sonamu UI**: 별도 포트가 아닌 API 서버의 `/sonamu-ui` 경로로 접근합니다. - API 서버 포트:
    `packages/api/src/sonamu.config.ts`에서 `port` 상수 수정 (이 경우 `packages/web/.sonamu.env`의
    `API_PORT`도 함께 수정 필요) - Web 앱 포트: `packages/web/vite.config.ts`에서 `server.port` 수정
</Note>

## 다음 단계

설치가 완료되었다면, [빠른 시작](/ko/getting-started/quick-start) 가이드를 통해 첫 번째 엔티티를 생성하고 API를 만들어보세요.
