Next.js + Prisma + Docker 풀스택 입문

CHZEE93·2026년 1월 31일

AI개발

목록 보기
3/11

Next.js + Prisma + Docker 풀스택 개발 가이드

1. 개요

React의 강력한 UI 라이브러리와 서버 사이드 기능을 결합한 Next.js, 데이터베이스를 쉽게 다루게 해주는 Prisma, 그리고 환경의 제약 없이 배포를 도와주는 Docker를 결합한 현대적인 웹 개발 스택 학습 정리입니다.

2. Next.js vs React.js 핵심 차이

특징React.js (CSR)Next.js (App Router)
렌더링클라이언트에서 UI 생성서버에서 미리 HTML 생성 (SSR/SSG)
라우팅라이브러리 설치 필요파일 시스템 기반 (폴더=URL)
백엔드별도의 API 서버 필요Server Actions로 직접 DB 접근 가능

3. 기술 스택별 핵심 구현 단계

Step 1: 프로젝트 생성 및 환경 구축

npx create-next-app@latest my-app
# TypeScript, Tailwind CSS, App Router 필수 선택

Step 2: Docker로 Database(PostgreSQL) 세팅

docker-compose.yml을 통해 로컬 설치 없이 DB 환경을 즉시 구축합니다.

services:
  db:
    image: postgres:15
    restart: always
    environment:
      POSTGRES_USER: myuser
      POSTGRES_PASSWORD: mypassword
      POSTGRES_DB: mymemo_db
    ports:
      - "5432:5432"

  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: "postgresql://.../mymemo_db"
    depends_on:
      - db

Step 3: Prisma ORM 설정

※ Prisma는 JavaScript / TypeScript에서 DB를 쉽게, 안전하게 쓰게 해주는 도

  1. Schema 정의: schema.prisma 파일에 데이터 모델을 설계합니다.
  2. Migration: npx prisma migrate dev 명령어로 DB에 테이블을 생성합니다.
  3. Generation: npx prisma generate를 통해 Type-safe한 클라이언트를 생성합니다.

Step 4: Server Actions를 활용한 데이터 처리

Next.js의 핵심 기능인 Server Actions를 사용하면 클라이언트 측 코드에서 직접 서버 함수를 호출하여 DB를 조작할 수 있습니다.

  • "use server" 지시어를 함수 상단에 선언
  • revalidatePath("/")를 사용해 데이터 변경 후 화면을 즉시 갱신
// src/app/page.tsx
import { db } from "@/lib/db";
import { revalidatePath } from "next/cache";

export default async function Home() {
  // 1. DB에서 데이터 불러오기 (Server Component의 위력!)
  const memos = await db.memo.findMany({
    orderBy: { createdAt: "desc" },
  });

  // 2. 데이터 저장을 위한 Server Action
  async function createMemo(formData: FormData) {
    "use server"; // 이 함수는 서버에서만 실행됨을 선언
    const content = formData.get("content") as string;
    
    if (content) {
      await db.memo.create({ data: { content } });
      revalidatePath("/"); // 데이터가 바뀌었으니 화면을 새로고침하라고 명령
    }
  }

  return (
    <main className="p-10 max-w-md mx-auto">
      <h1 className="text-2xl font-bold mb-5">나의 메모장</h1>

      {/* 메모 작성 폼 */}
      <form action={createMemo} className="flex gap-2 mb-8">
        <input
          name="content"
          className="border p-2 flex-1 rounded text-black"
          placeholder="메모를 입력하세요..."
          required
        />
        <button className="bg-blue-500 text-white px-4 py-2 rounded">저장</button>
      </form>

      {/* 메모 리스트 출력 */}
      <ul className="space-y-2">
        {memos.map((memo) => (
          <li key={memo.id} className="p-3 border-b flex justify-between">
            <span>{memo.content}</span>
            <span className="text-xs text-gray-400">
              {memo.createdAt.toLocaleTimeString()}
            </span>
          </li>
        ))}
      </ul>
    </main>
  );
}

4. Docker를 이용한 배포 자동화

Dockerfile을 작성하여 앱을 이미지화하고, docker-compose를 통해 앱 서버와 DB 서버를 하나의 네트워크로 묶어 실행합니다.

# Dockerfile 요약
FROM node:20-alpine AS base

# 1. 의존성 설치
FROM base AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci

# 2. 빌드 단계
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Prisma Client 생성 포함
RUN npx prisma generate
RUN npm run build

# 3. 실행 단계
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./package.json

EXPOSE 3000
CMD ["npm", "start"]

기타사항

1. Prisma 7에서는 기존 버전보다 “연결 방식을 명확히 선언하는 ORM"

import { PrismaClient } from "@prisma/client";
import { PrismaPg } from "@prisma/adapter-pg";
import { Pool } from "pg";

const pool = new Pool({
  connectionString: process.env.DATABASE_URL!,
});

const adapter = new PrismaPg(pool);

const globalForPrisma = globalThis as unknown as {
  prisma: PrismaClient | undefined;
};

export const db =
  globalForPrisma.prisma ??
  new PrismaClient({
    adapter,
  });

if (process.env.NODE_ENV !== "production") {
  globalForPrisma.prisma = db;
}

2. Docker 파일 분석

Dockerfile (Next.js 앱의 이미지 생성)

이 파일은 우리 Next.js 코드를 실행 가능한 이미지로 만드는 과정을 기술합니다.

  • Multi-stage Build: deps, builder, runner 단계를 나누는 이유는 최종 이미지의 크기를 줄이기 위해서입니다. 실제 실행에 필요 없는 빌드 도구들을 제거하고 가벼운 결과물만 남깁니다.
  • npx prisma generate: 빌드 시점에 Prisma 클라이언트를 생성해야 이미지 안에서도 DB 타입을 인식할 수 있습니다.

docker-compose.yml (멀티 컨테이너 관리)

앱과 DB처럼 여러 개의 컨테이너가 서로 협력해야 할 때 사용합니다.

  • depends_on: DB가 먼저 실행된 후에 Next.js 앱이 실행되도록 순서를 보장합니다.
  • 네트워크: Docker Compose 내부에서 Next.js 앱은 DB에 접속할 때 localhost가 아닌 서비스 이름(db)으로 통신할 수 있습니다. (예: postgresql://...@db:5432/...)
profile
치즈 키우는 사람

0개의 댓글