NestJS에서 Prisma 7와 Docker 및 Docker Compose 사용 완전 가이드

발행: (2026년 2월 2일 오전 12:56 GMT+9)
12 분 소요
원문: Dev.to

Source: Dev.to

만약 Docker 안에서 Prisma를 실행해 보았고, 전혀 이해할 수 없는 연결 오류에 갇힌 적이 있다면, 이 글이 도움이 될 것입니다.

현대 백엔드 애플리케이션은 데이터베이스 접근을 위해 Prisma, TypeORM, Mongoose와 같은 ORM에 의존하는 경우가 많으며, 일관된 개발 환경을 위해 Docker를 함께 사용합니다. 각각의 도구는 독립적으로 잘 동작하지만, Prisma를 Docker와 결합—특히 컨테이너화된 데이터베이스와 함께 사용할 때—는 생각보다 까다로울 수 있습니다.

TL;DR – 나는 Prisma가 Docker에서 실행 중인 PostgreSQL 데이터베이스에 연결되지 않는 원인을 디버깅하는 데 거의 이틀을 보냈다. 이 가이드는 단계별 설정, 흔히 발생하는 함정, 그리고 컨테이너화된 환경에서 마이그레이션을 실행하기 위한 모범 사례를 안내한다.

📋 필수 조건

  • NestJS에 대한 기본 지식
  • DockerDocker‑Compose에 대한 기본 이해
  • Docker Desktop이 설치되고 실행 중
  • 코드 편집기 (예: VS Code)

Prisma란?

Prisma는 테이블을 JavaScript/TypeScript 객체에 매핑하여 데이터베이스 작업을 단순화하는 오픈‑소스 ORM(Object‑Relational Mapper)입니다. 원시 SQL을 직접 작성하는 대신, 타입‑안전 API를 사용해 데이터베이스와 상호작용합니다.

// Raw SQL
SELECT * FROM users WHERE email = 'john@example.com';

// Prisma
const user = await prisma.user.findUnique({
  where: { email: 'john@example.com' },
});

장점

  • 가독성 향상
  • 런타임 오류 감소
  • 뛰어난 TypeScript 지원 제공

Prisma 7 하이라이트 (Docker와 관련)

기능Docker와 관련된 이유
Rust‑free 클라이언트 엔진특히 Alpine 이미지에서 바이너리 호환성 문제가 적음
타입 정의 감소TypeScript 컴파일 속도 향상, 에디터 성능 개선
현대 JavaScript 지원새로운 Node.js 런타임과 일치
보다 깔끔한 개발자 경험구성이 간소화되고, 엣지 케이스 오류가 감소

최소 요구 사항

  • Node.js 20.19.0+
  • TypeScript 5.4.0+

왜 Docker인가?

Docker는 애플리케이션과 그 종속성을 컨테이너에 패키징하여 어디서나 동일하게 실행되도록 보장합니다.

장점

  • 팀 간 일관된 환경
  • 빠른 온보딩
  • 더 쉬운 배포 및 확장
  • “내 컴퓨터에서는 작동해요” 문제 감소

NestJS 개요

NestJS는 효율적이고 확장 가능한 Node.js 서버‑사이드 애플리케이션을 구축하기 위한 프레임워크입니다. TypeScript로 구축되었으며 다음을 지원합니다:

  • 객체 지향 프로그래밍 (OOP)
  • 함수형 프로그래밍 (FP)
  • 함수형 반응형 프로그래밍 (FRP)

내부적으로 기본적으로 Express를 사용합니다 (원한다면 Fastify도 가능합니다).

NestJS CLI를 전역으로 설치하기

npm install -g @nestjs/cli

새 프로젝트 만들기

nest new backend

스캐폴드:

  • TypeScript 설정
  • 프로젝트 구조
  • 핵심 의존성

필요에 따라 컨트롤러/서비스를 생성합니다:

nest g controller users
nest g service users

NestJS 프로젝트에 Prisma 추가

1️⃣ Prisma 패키지 설치

# Development dependencies
npm install prisma @types/pg --save-dev

# Runtime dependencies
npm install @prisma/client @prisma/adapter-pg pg dotenv

2️⃣ Prisma 초기화

npx prisma init

prisma/ 디렉터리가 생성되고 schema.prisma.env 파일이 만들어집니다.

3️⃣ Prisma 클라이언트 제너레이터 설정 (Prisma 7)

prisma/schema.prisma(또는 별도 prisma.config.ts)에 다음을 추가합니다:

generator client {
  provider     = "prisma-client"
  output       = "../src/generated/prisma"
  moduleFormat = "cjs"
}

4️⃣ NestJS Prisma 모듈 및 서비스 생성

nest g module prisma
nest g service prisma

src/prisma/prisma.service.ts

import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
import { PrismaPg } from '@prisma/adapter-pg';
import { PrismaClient } from 'src/generated/prisma/client';

@Injectable()
export class PrismaService
  extends PrismaClient
  implements OnModuleInit, OnModuleDestroy
{
  constructor() {
    const adapter = new PrismaPg({
      connectionString: process.env.DATABASE_URL,
    });
    super({ adapter, log: ['query', 'info', 'warn', 'error'] });
  }

  async onModuleInit() {
    await this.$connect();
  }

  async onModuleDestroy() {
    await this.$disconnect();
  }
}

이 서비스:

  • prisma/ 디렉터리를 생성하고 schema.prisma를 생성합니다
  • .env 파일을 추가합니다(없을 경우)
  • prisma.config.ts를 생성합니다(Prisma 7에서 새로 추가)

Dockerising PostgreSQL (stand‑alone container)

Tip: 진행하기 전에 Docker Desktop이 실행 중인지 확인하세요.

1️⃣ 프로젝트 루트에 docker-compose.yml 만들기

services:
  postgres:
    image: postgres:15
    restart: always
    environment:
      POSTGRES_DB: postgres
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: backend
    ports:
      - "5432:5432"
    networks:
      - prisma-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"]
      interval: 5s
      timeout: 2s
      retries: 20
    volumes:
      - postgres_data:/var/lib/postgresql/data
    logging:
      options:
        max-size: "10m"
        max-file: "3"

networks:
  prisma-network:

volumes:
  postgres_data:

2️⃣ DB 실행하기

docker compose up -d

3️⃣ 연결 문자열 설정하기

.env 파일에 추가하거나 기존 DATABASE_URL을 교체합니다:

DATABASE_URL="postgresql://postgres:backend@localhost:5432/postgres?schema=public"

Note: 머신에서 localhost가 동작하지 않으면 127.0.0.1을 사용하세요.

4️⃣ 첫 번째 마이그레이션 실행 및 클라이언트 생성

npx prisma migrate dev --name initial-migration
npx prisma generate

5️⃣ NestJS 앱 시작 및 Prisma Studio 열기

npm run start   # or npm run dev
npx prisma studio

이제 Prisma와 Dockerized PostgreSQL 인스턴스를 백엔드로 사용하는 정상적인 NestJS API를 확인할 수 있습니다.

NestJS 서버용 Docker 이미지 빌드

프로젝트 루트에 Dockerfile을 생성합니다. Prisma 7에서는 Alpine 기반 이미지와 Slim 기반 이미지 모두를 지원합니다.

예시 Dockerfile (Alpine)

# Use the LTS Alpine image (lightweight)
FROM node:lts-alpine

# Set working directory
WORKDIR /usr/src/app

# Install production dependencies
COPY package.json package-lock.json ./
RUN npm ci --omit=dev

# Copy source code
COPY . .

# Run DB migrations then start the server
CMD ["sh", "-c", "npm run db:deploy && npm run dev"]

대체 베이스 이미지

  • node:lts-slim – 약간 더 크지만 안정적임
  • node:lts – 전체 Debian 기반 이미지

Source:

docker‑compose.yml에 서버 추가하기

기존 파일에 server 서비스를 확장하여 Dockerfile을 빌드하도록 합니다.

services:
  postgres:
    # ... (same as before)

  server:
    build:
      context: .
      dockerfile: Dockerfile
    depends_on:
      postgres:
        condition: service_healthy
    environment:
      DATABASE_URL: "postgresql://postgres:backend@postgres:5432/postgres?schema=public"
    ports:
      - "3000:3000"
    networks:
      - prisma-network
    command: ["sh", "-c", "npm run db:deploy && npm run start:prod"]

핵심 포인트

  • depends_on 은 DB가 정상 상태가 될 때까지 NestJS 애플리케이션이 시작되지 않도록 보장합니다.
  • DATABASE_URL 은 Docker 네트워크 내부의 서비스 이름(postgres)을 가리키며, localhost 가 아닙니다.

전체 실행하기

docker compose up -d

NestJS API는 http://localhost:3000 에서, Prisma Studio는 (노출된 경우) http://localhost:5555 에서 접근할 수 있습니다.

일반적인 함정 및 회피 방법

증상가능한 원인해결 방법
PrismaClientInitializationError: Unable to connect to database잘못된 호스트 (localhost 대신 서비스 이름)Docker 내부에서 실행할 때 DATABASE_URLpostgres(서비스 이름)를 사용하세요
binary not found or unsupported platform오래된 Rust‑based 엔진을 사용하는 Alpine 이미지 사용Prisma 7(Rust‑free)으로 업그레이드하거나 Alpine이 아닌 베이스로 전환하세요
Migrations keep failing마이그레이션 실행 시 DB가 준비되지 않음Docker healthcheck와 depends_oncondition: service_healthy를 사용하세요
TypeScript compilation slows down타입 정의가 너무 많음 (pre‑Prisma 7)Prisma 7으로 업그레이드 – 정의가 줄어들고 빌드가 빨라집니다

요약

  1. NestJS 설정 및 Prisma 추가.
  2. Dockerized PostgreSQL 서비스를 healthcheck와 함께 생성.
  3. Prisma 클라이언트를 Docker 네트워크 호스트를 사용하도록 구성.
  4. 서버 시작 전에 마이그레이션 실행 (npx prisma migrate dev).
  5. 가벼운 Node 이미지로 NestJS 앱을 Dockerize.
  6. docker‑compose.yml 로 모든 것을 Compose하고 실행.

이제 Prisma 7, Docker, NestJS가 원활하게 함께 작동하는 재현 가능한 컨테이너‑우선 개발 환경을 갖추었습니다. 즐거운 코딩 되세요! 🚀

Docker Compose 설정

services:
  app:
    context: .
    dockerfile: Dockerfile
    ports:
      - "3000:3000"
    stdin_open: true
    tty: true
    depends_on:
      postgres_db:
        condition: service_healthy
    env_file:
      - .env.prod
    networks:
      - prisma-network

networks:
  prisma-network:
    name: prisma-network

환경 파일

각 환경에 대해 두 개의 별도 파일을 생성합니다:

  • .env.dev
  • .env.prod

두 파일 모두 데이터베이스 연결 문자열을 포함해야 합니다:

DATABASE_URL="postgresql://postgres:prisma@postgres_db:5432/postgres?schema=public"

컨테이너 실행

  • 분리 모드 (로그 감소)

    docker compose up --build -d
  • 전체 로그

    docker compose up --build

Tip: -d 플래그를 추가하면 컨테이너가 분리 모드로 실행되어 대부분의 로그 출력이 억제됩니다.

일반적인 함정 및 해결책

문제해결책
Docker 내부에서는 localhost가 컨테이너 자체를 가리킵니다.대신 Docker 서비스 이름을 사용하세요: postgres_db:5432.
컨테이너가 PostgreSQL이 준비되기 전에 시작될 수 있습니다.마이그레이션을 실행하기 전에 대기 스크립트를 추가하거나 Docker 헬스 체크를 사용하세요.
컨테이너 내부에서 Prisma Client가 생성되지 않아 충돌이 발생합니다.Docker 빌드 단계에서 npx prisma generate를 실행하세요.
구버전 Prisma는 Alpine 이미지와 호환성 문제가 있습니다.Prisma 7로 업그레이드하세요 – Rust‑없는 클라이언트 엔진으로 이 문제를 크게 줄일 수 있습니다.

왜 Prisma 7을 Docker 및 Docker‑Compose와 함께 사용할까?

  • 신뢰할 수 있는 마이그레이션 – 헬스 체크를 통해 DB가 준비된 후에 적용됩니다.
  • 환경에 구애받지 않음 – 별도의 .env 파일을 사용하면 특정 환경에서만 나타나는 버그를 방지할 수 있습니다.
  • 확장 가능한 워크플로우 – 동일한 설정이 로컬 개발부터 프로덕션까지 모두 작동합니다.

이 가이드가 도움이 되었다면, 좋아요, 댓글, 공유를 자유롭게 해 주세요.
전체 예제 저장소를 확인해 보세요:

🔗 https://github.com/idongesit98/DockerProject

Back to Blog

관련 글

더 보기 »