> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-vortex-format.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# ClickHouse Managed Postgres에서 Prisma 사용하기

> Prisma ORM으로 TypeScript 앱을 ClickHouse Managed Postgres에 연결하고, Prisma Migrate로 마이그레이션을 실행하며, 인증서 검증을 거친 TLS 연결로 PgBouncer를 통해 쿼리를 수행하는 방법을 설명합니다

export const BetaBadge = ({link, galaxyTrack, galaxyEvent}) => {
  if (link) {
    return <a href={link} target="_blank" rel="noopener noreferrer" className="betaBadge" onClick={galaxyTrack && galaxyEvent ? galaxyOnClick(galaxyEvent) : undefined}>
                <span>베타</span>
            </a>;
  }
  return <a href="https://clickhouse.com/docs/reference/settings/beta-and-experimental-features#beta-features" className="betaBadge">
            <span>베타 기능</span>
        </a>;
};

<BetaBadge link="https://clickhouse.com/cloud/postgres" galaxyTrack={true} galaxyEvent="docs.managed-postgres.guides-prisma-beta" />

[Prisma ORM](https://www.prisma.io/orm)은 선언적 스키마, 마이그레이션 도구(Prisma Migrate), 자동 생성되는 타입 안전(type-safe) 클라이언트를 제공하는 TypeScript ORM입니다. 이 가이드에서는 Prisma를 ClickHouse Managed Postgres에 연결하고, 마이그레이션으로 테이블을 생성한 뒤, 스크립트와 간단한 HTTP 엔드포인트에서 해당 테이블을 쿼리합니다.

이 가이드에서는 현재 안정 릴리스인 Prisma ORM 7(`7.10.0`에서 테스트됨)을 사용합니다.

<h2 id="prerequisites">
  사전 요구 사항
</h2>

* Node.js 20.19, 22.12 또는 24 이상
* ClickHouse Managed Postgres 서비스
* 데이터베이스 생성에 사용할 [`psql`](https://www.postgresql.org/download/). [SQL 콘솔](/ko/integrations/connectors/sql-clients/sql-console)에서 `CREATE DATABASE` SQL 문을 실행해도 됩니다.
* macOS 사용 시: Prisma Migrate 실행에 필요한 [Docker](https://docs.docker.com/get-started/get-docker/) ([마이그레이션 실행](#migrate) 참조)

<h2 id="create-service">
  ClickHouse Managed Postgres 서비스 생성
</h2>

ClickHouse Cloud 콘솔에서 **New service**를 클릭한 후 **Postgres**를 선택하십시오. 인스턴스는 몇 분 안에 준비됩니다. 자세한 단계별 안내는 [빠른 시작 가이드](/ko/products/managed-postgres/quickstart)를 참조하십시오.

<h2 id="connection-details">
  연결 정보 확인
</h2>

서비스의 왼쪽 사이드바에서 **Connect**를 클릭합니다. 모달에 사용자 이름, 비밀번호, 서버, 포트와 함께 바로 사용할 수 있는 연결 문자열(connection string)이 표시됩니다.

Prisma에는 데이터베이스와 통신하는 구성 요소가 두 가지 있으므로, 이 가이드에서는 연결을 두 개 사용합니다.

* **애플리케이션(Prisma Client)** 은 포트 `6432`에서 **PgBouncer를 통해** 연결합니다. PgBouncer가 연결을 풀링하므로 여러 앱 프로세스나 서버리스 인스턴스가 소수의 Postgres 백엔드를 공유할 수 있습니다.
* **Prisma CLI(Prisma Migrate)** 는 포트 `5432`에서 **직접** 연결합니다. Prisma Migrate는 실행되는 동안 세션 수준의 권고 잠금(advisory lock)을 획득합니다. PgBouncer의 트랜잭션 풀링 모드에서는 이 잠금이 풀링된 백엔드에 그대로 남은 채 해당 백엔드가 다른 클라이언트의 요청을 처리할 수 있으며, 그 결과 이후의 마이그레이션이 이 잠금에 막혀 진행되지 않습니다.

모달 상단에서 **Directly**와 **via PgBouncer**를 전환하면 각 포트를 확인할 수 있습니다. 서버와 자격 증명은 두 연결 모두 동일하며, 포트만 다릅니다.

**via PgBouncer**를 선택한 상태에서 **Download CA certificate**를 클릭합니다. **Directly**를 선택한 경우에는 먼저 **Use SSL**을 켜야 버튼이 표시됩니다. 파일 이름은 `<service-name>-ca-certificate.pem`이며, **Settings → CA Certificate**에서도 찾을 수 있습니다. 이 인증서는 인스턴스마다 고유하며, `sslmode=verify-full`로 연결할 때 사용합니다. 이 모드에서는 통신 중인 서버가 실제로 자신의 서버인지 검증합니다.

<h2 id="setup">
  프로젝트 설정
</h2>

TypeScript 프로젝트를 생성하고 Prisma CLI, Prisma Client, [node-postgres](https://node-postgres.com/) 드라이버 어댑터 및 `dotenv`를 설치하십시오.

```bash theme={null}
mkdir hello-prisma
cd hello-prisma
npm init -y
npm pkg set type=module
npm install typescript tsx @types/node @types/pg --save-dev
npm install prisma@7 --save-dev
npm install @prisma/client@7 @prisma/adapter-pg pg dotenv
```

<Note>
  `prisma@7`과 `@prisma/client@7`을 명시적으로 설치하십시오. 이 문서의 작성 시점 기준으로 `prisma`의 npm `latest` 태그는 Prisma 8 릴리스 후보(release candidate)를 가리키며, 이 버전은 본 가이드와 설정 방식이 다릅니다.
</Note>

`tsconfig.json` 파일을 생성하세요:

```json theme={null}
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler",
    "target": "ES2023",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "types": ["node"]
  }
}
```

<Tip>
  **기존 앱에 추가하는 경우**

  `mkdir`, `npm init`, `tsconfig.json` 단계는 건너뛰세요. 프로젝트에서 `npm install tsx @types/pg prisma@7 --save-dev`와 `npm install @prisma/client@7 @prisma/adapter-pg pg dotenv`를 실행한 다음 [Prisma 초기화](#init) 단계부터 진행하세요.
</Tip>

<h2 id="init">
  Prisma 초기화
</h2>

<Steps>
  <Step title="prisma init 실행">
    ```bash theme={null}
    npx prisma init --datasource-provider postgresql --output ../generated/prisma
    ```

    이 명령어는 `prisma/schema.prisma`와 Prisma 구성 파일인 `prisma7.config.ts`를 생성합니다. 또한 `.env`에는 플레이스홀더 `DATABASE_URL`을, `.gitignore`에는 생성된 클라이언트를 추가하고(해당 파일이 없으면 새로 생성합니다), AI 코딩 에이전트용 Prisma 스킬도 추가합니다. Prisma 7.10 이상에서는 Prisma 8 포맷과 충돌하지 않도록 구성 파일 이름을 `prisma7.config.ts`로 지정합니다.
  </Step>

  <Step title="CA 인증서 추가">
    다운로드한 CA 인증서를 프로젝트 루트로 옮긴 후 이름을 `ca-certificate.pem`으로 변경하세요.

    ```bash theme={null}
    mv ~/Downloads/<service-name>-ca-certificate.pem ca-certificate.pem
    ```

    인증서의 상대 경로는 명령어를 실행하는 디렉터리를 기준으로 해석됩니다. 따라서 이 가이드의 모든 명령어는 프로젝트 루트에서 실행하세요.
  </Step>
</Steps>

<h2 id="configure">
  연결 구성
</h2>

<Steps>
  <Step title="데이터베이스 생성">
    앱에서 사용할 데이터베이스를 생성합니다. `<PASSWORD>`와 호스트를 **Connect** 모달에 표시된 값으로 바꾸세요:

    ```bash theme={null}
    psql "postgresql://postgres:<PASSWORD>@your-instance.pg.clickhouse.cloud:5432/postgres?sslmode=verify-full&sslrootcert=ca-certificate.pem" -c "CREATE DATABASE guide_prisma;"
    ```

    ```text theme={null}
    CREATE DATABASE
    ```
  </Step>

  <Step title="연결 URL 설정">
    `.env`에서 `prisma init`이 추가한 플레이스홀더 `DATABASE_URL`을 아래의 연결 URL 2개로 바꾸세요. 두 URL 모두 `guide_prisma` 데이터베이스를 가리킵니다. 비밀번호는 Connect 모달에 표시된 값을 사용하세요:

    ```bash theme={null}
    # Prisma Client(애플리케이션): PgBouncer 경유, 포트 6432
    DATABASE_URL="postgresql://postgres:<PASSWORD>@your-instance.pg.clickhouse.cloud:6432/guide_prisma?sslmode=verify-full&sslrootcert=ca-certificate.pem"

    # Prisma CLI(마이그레이션): 직접 연결, 포트 5432
    DIRECT_URL="postgresql://postgres:<PASSWORD>@your-instance.pg.clickhouse.cloud:5432/guide_prisma?sslmode=require&sslaccept=strict&sslcert=ca-certificate.pem"
    ```

    두 URL을 읽는 드라이버가 서로 다르기 때문에 TLS 매개변수도 서로 다릅니다:

    * \*\*`DATABASE_URL`\*\*은 `@prisma/adapter-pg`를 통해 node-postgres가 읽습니다. Connect 모달에 표시된 것과 동일한 표준 매개변수인 `sslmode=verify-full&sslrootcert=...`를 지원합니다.
    * \*\*`DIRECT_URL`\*\*은 Prisma CLI의 스키마 엔진이 읽으며, 이 엔진은 자체 매개변수를 사용합니다. `sslcert`는 CA 인증서의 경로를 지정하고, `sslaccept=strict`는 인증서 및 호스트명 검증을 활성화합니다.

    <Warning>
      Prisma CLI용 URL에는 `sslmode=verify-full&sslrootcert=...`를 사용하지 마십시오. 스키마 엔진은 `sslrootcert`를 무시하며, `sslaccept=strict`가 없으면 서버 인증서를 전혀 검증하지 않습니다. 따라서 연결은 암호화되지만 인증은 이루어지지 않습니다.
    </Warning>
  </Step>

  <Step title="Prisma CLI가 직접 연결을 사용하도록 설정">
    `prisma7.config.ts`의 내용을 다음과 같이 바꾸세요:

    ```typescript theme={null}
    import "dotenv/config";
    import { defineConfig, env } from "prisma/config";

    export default defineConfig({
      schema: "prisma/schema.prisma",
      migrations: {
        path: "prisma/migrations",
      },
      datasource: {
        url: env("DIRECT_URL"),
      },
    });
    ```

    Prisma 7에서 구성 파일의 URL은 CLI에서만 사용됩니다. Prisma Client는 드라이버 어댑터를 통해 연결하며, 드라이버 어댑터는 [데이터베이스 쿼리](#query)에서 구성합니다.
  </Step>
</Steps>

<h2 id="migrate">
  스키마 정의 및 마이그레이션 실행
</h2>

<Steps>
  <Step title="모델 추가">
    `prisma/schema.prisma` 파일 끝에 `Todo` 모델을 추가합니다.

    ```prisma theme={null}
    model Todo {
      id        Int      @id @default(autoincrement())
      title     String
      done      Boolean  @default(false)
      createdAt DateTime @default(now())
    }
    ```
  </Step>

  <Step title="마이그레이션 실행">
    Linux에서는 Prisma Migrate를 직접 실행합니다.

    ```bash theme={null}
    npx prisma migrate dev --name init
    ```

    macOS에서는 동일한 명령어를 Linux 컨테이너에서 실행합니다.

    ```bash theme={null}
    docker run --rm -it -v "$PWD":/app -w /app node:24 npx prisma migrate dev --name init
    ```

    <Warning>
      ClickHouse Managed Postgres는 TLS 1.3만 허용합니다. macOS에서는 Prisma CLI의 스키마 엔진이 시스템 TLS 라이브러리를 사용하는데, 이 라이브러리로는 해당 설정에서 연결할 수 없습니다. 이 경우 `P1011: Error opening a TLS connection: One or more parameters passed to a function were not valid` 오류가 발생하고, `sslcert`를 제거하면 `bad protocol version` 오류가 발생합니다([prisma/orm#29600](https://github.com/prisma/orm/issues/29600)). 이 문제는 `prisma migrate`, `prisma db pull`처럼 데이터베이스에 연결하는 CLI 명령어에만 해당합니다. Prisma Client는 node-postgres를 통해 연결하므로 영향을 받지 않습니다. CLI를 Linux 컨테이너나 Linux 기반 CI 파이프라인에서 실행하면 이 문제를 우회할 수 있습니다.
    </Warning>

    Prisma는 `prisma/migrations/`에 SQL 마이그레이션을 생성한 뒤 적용합니다.

    ```text theme={null}
    Applying migration `20260930165244_init`

    The following migration(s) have been created and applied from new schema changes:

    prisma/migrations/
      └─ 20260930165244_init/
        └─ migration.sql

    Your database is now in sync with your schema.
    ```
  </Step>

  <Step title="Prisma Client 생성">
    ```bash theme={null}
    npx prisma generate
    ```

    클라이언트는 `generated/prisma`에 생성됩니다. 이 명령어는 데이터베이스에 연결하지 않으므로 어떤 플랫폼에서든 실행할 수 있습니다.
  </Step>
</Steps>

<h2 id="query">
  데이터베이스 쿼리
</h2>

<Steps>
  <Step title="Prisma Client 생성">
    `lib/prisma.ts`를 생성하십시오. `PrismaPg` 어댑터는 PgBouncer를 통해 `DATABASE_URL`로 연결합니다:

    ```typescript theme={null}
    import "dotenv/config";
    import { PrismaPg } from "@prisma/adapter-pg";
    import { PrismaClient } from "../generated/prisma/client";

    const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });

    export const prisma = new PrismaClient({ adapter });
    ```

    <Tip>
      **PgBouncer 설정 불필요**

      `@prisma/adapter-pg`는 각 쿼리를 이름 없는 prepared statement로 전송하고 `DEALLOCATE`를 실행하지 않으므로 PgBouncer의 트랜잭션 풀링 모드에서도 정상적으로 동작합니다. 풀링된 여러 백엔드에서 서로 다른 쿼리 수백 개가 동시에 실행되더라도 오류 없이 처리합니다. 이전 Prisma 버전에서 사용하던 `pgbouncer=true` URL 매개변수는 필요하지 않으며, 드라이버 어댑터를 사용할 때는 아무런 효과가 없습니다.
    </Tip>
  </Step>

  <Step title="CRUD 쿼리 실행">
    `script.ts`를 생성하십시오:

    ```typescript theme={null}
    import { prisma } from "./lib/prisma";

    async function main() {
      // 생성
      const todo = await prisma.todo.create({
        data: { title: "Connect Prisma to ClickHouse Managed Postgres" },
      });
      console.log("Created:", todo);

      // 조회
      const open = await prisma.todo.findMany({ where: { done: false } });
      console.log("Open todos:", open.length);

      // 수정
      const updated = await prisma.todo.update({
        where: { id: todo.id },
        data: { done: true },
      });
      console.log("Updated:", updated);

      // 삭제
      await prisma.todo.delete({ where: { id: todo.id } });
      console.log("Deleted todo", todo.id);
    }

    main().finally(() => prisma.$disconnect());
    ```

    스크립트를 실행하십시오:

    ```bash theme={null}
    npx tsx script.ts
    ```

    ```text theme={null}
    Created: {
      id: 1,
      title: 'Connect Prisma to ClickHouse Managed Postgres',
      done: false,
      createdAt: 2026-09-30T16:52:57.116Z
    }
    Open todos: 1
    Updated: {
      id: 1,
      title: 'Connect Prisma to ClickHouse Managed Postgres',
      done: true,
      createdAt: 2026-09-30T16:52:57.116Z
    }
    Deleted todo 1
    ```
  </Step>

  <Step title="HTTP로 데이터 제공">
    `server.ts`를 생성하십시오. 이 파일은 `POST /todos` 요청으로 할 일을 생성하고, 모든 `GET` 요청에 대해 할 일 목록을 반환하는 최소한의 HTTP 서버입니다:

    ```typescript theme={null}
    import { createServer } from "node:http";
    import { prisma } from "./lib/prisma";

    const port = Number(process.env.PORT ?? 3000);

    createServer(async (req, res) => {
      if (req.method === "POST" && req.url === "/todos") {
        let body = "";
        for await (const chunk of req) body += chunk;
        const todo = await prisma.todo.create({ data: { title: JSON.parse(body).title } });
        res.writeHead(201, { "Content-Type": "application/json" });
        res.end(JSON.stringify(todo));
        return;
      }

      const todos = await prisma.todo.findMany({ orderBy: { id: "asc" } });
      res.writeHead(200, { "Content-Type": "application/json" });
      res.end(JSON.stringify(todos, null, 2));
    }).listen(port, () => console.log(`Listening on http://localhost:${port}`));
    ```

    서버를 시작하십시오:

    ```bash theme={null}
    npx tsx server.ts
    ```

    다른 터미널을 열고 할 일 2개를 추가하십시오:

    ```bash theme={null}
    curl -X POST localhost:3000/todos -H "Content-Type: application/json" -d '{"title": "Try Prisma with ClickHouse Managed Postgres"}'
    curl -X POST localhost:3000/todos -H "Content-Type: application/json" -d '{"title": "Add a read replica"}'
    ```

    브라우저에서 [http://localhost:3000/todos](http://localhost:3000/todos)를 열어 추가된 항목을 확인하십시오. 응답은 다음과 같습니다:

    ```json theme={null}
    [
      {
        "id": 2,
        "title": "Try Prisma with ClickHouse Managed Postgres",
        "done": false,
        "createdAt": "2026-09-30T16:53:06.098Z"
      },
      {
        "id": 3,
        "title": "Add a read replica",
        "done": false,
        "createdAt": "2026-09-30T16:53:06.184Z"
      }
    ]
    ```
  </Step>
</Steps>

<h2 id="verify">
  SQL 콘솔에서 확인하기
</h2>

ClickHouse Cloud 콘솔에서 해당 서비스의 **SQL 콘솔**을 열고, 데이터베이스와 `public` 스키마를 펼친 다음 `Todo` 테이블을 선택하십시오. Prisma Migrate가 적용된 마이그레이션을 기록하는 `_prisma_migrations` 테이블도 함께 표시됩니다.

`Todo` 테이블에는 HTTP 엔드포인트를 통해 추가한 2개의 행이 저장되어 있습니다.

| id | title | done | createdAt |
| - | - | - | - |
| 2 | Try Prisma with ClickHouse Managed Postgres | false | 2026-09-30 16:53:06.098 |
| 3 | Add a read replica | false | 2026-09-30 16:53:06.184 |

<h2 id="troubleshooting">
  문제 해결
</h2>

| 오류 | 원인 및 해결 방법 |
| - | - |
| `P1011: Error opening a TLS connection: One or more parameters passed to a function were not valid` 또는 `bad protocol version` | Prisma CLI가 macOS에서 실행되고 있습니다. [마이그레이션 실행](#migrate)에 나온 대로 Linux 컨테이너에서 실행하십시오. |
| `P1011: ... certificate verify failed` | Prisma CLI가 서버를 검증하지 못했습니다. `DIRECT_URL`의 `sslcert`가 인스턴스의 CA 인증서를 가리키는지 확인하십시오. |
| `P1011: ... cert file not found` | `DIRECT_URL`의 `sslcert` 경로가 잘못되었습니다. 프로젝트 루트에서 CLI를 실행하거나 절대 경로를 사용하십시오. |
| `unable to verify the first certificate` | Prisma Client가 서버를 검증하지 못했습니다. `DATABASE_URL`의 `sslrootcert`가 인스턴스의 CA 인증서를 가리키는지 확인하십시오. |
| `ENOENT: no such file or directory` | `DATABASE_URL`의 `sslrootcert` 경로가 잘못되었습니다. 프로젝트 루트에서 애플리케이션을 실행하거나 절대 경로를 사용하십시오. |

<h2 id="next-steps">
  다음 단계
</h2>

* [연결](/ko/products/managed-postgres/connection): 연결 문자열(connection string), PgBouncer 및 TLS
* [설정](/ko/products/managed-postgres/settings): Postgres 및 PgBouncer 매개변수 조정
* [읽기 레플리카(Read replica)](/ko/products/managed-postgres/read-replicas): 읽기 작업이 많은 워크로드 확장
* [로컬 개발](/ko/products/managed-postgres/local-development): Docker에서 실행되는 로컬 Postgres로 개발
* [프로덕션 환경의 Prisma Migrate](https://www.prisma.io/docs/orm/prisma-migrate/workflows/development-and-production): CI 파이프라인에서 `prisma migrate deploy` 사용
