1편. Prisma 개발환경 구축과 프로젝트 초기화 (Node.js + Prisma 7)
📚 목차
1. 개발환경 구축 및 프로젝트 초기화
2. DB 연동 및 스키마 설계 (PostgreSQL)
3. Prisma 설정 및 싱글톤 클라이언트 구현
4. Prisma CLI 주요 명령어 요약
📂 [GitHub 예시 코드 보러가기] (https://github.com/cericube/nodejs-tutorials) /Prisma
1. 개발환경 구축 및 프로젝트 초기화
Prisma는 Node.js에서 데이터베이스를 다룰 때, SQL을 직접 작성하는 방식과 비교하여 다음을 제공하는 ORM 계열 도구입니다.
✔️ 개발환경 구축하기
Node.js 개발환경 구축하기 : JavaScript, TypeScript, Vitest
Node.js 개발환경 구축하기 : JavaScript, TypeScript, Vitest
1. Visual Studio Code 설치Visual Studio Code 설치 방법 (Installer / Zip 포터블 모드) Visual Studio Code 설치 방법 (Installer / Zip 포터블 모드)Windows에서 Visual Studio Code(이하 VSCode)를 설치하는 방법에는 설치형(Instal
quadcube.tistory.com
✔️ Prisma VS Code 확장설치

Prisma VS Code Extension은 데이터베이스 관리 UI, 문법 강조, 린팅, 코드 자동 완성, 포맷팅, 정의로 이동(Jump-to-Definition) 등 Prisma 개발에 필요한 다양한 기능을 VS Code 안에서 제공합니다.
.vscode/settings.json 설정 예시
{
"editor.formatOnSave": true,
"[prisma]": {
"editor.defaultFormatter": "Prisma.prisma"
},
//이 확장은 사용 현황을 개선하기 위해 텔레메트리 데이터를 수집합니다.
//텔레메트리 비활성화 방법
"telemetry.telemetryLevel": "off"
}
🔷 Prisma 7.x 특징
https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-7
| 구분 | v6이하 | v7.x |
| 설치 편의성 | 매우 쉬움 (Prisma가 대부분 자동 처리) | 다소 번거로움 (DB 드라이버 직접 설치 필요) |
| 엔진 무게 | 무거움 (수십 MB 규모의 Rust 바이너리) | 매우 가벼움 (Pure JS / WASM 기반) |
| 통신 구조 | JS ↔ Rust Engine ↔ DB | JS ↔ JS(pg 등 드라이버) ↔ DB |
| 성능 (응답 속도) | 보통 (직렬화·IPC 오버헤드 존재) | 매우 빠름 (중간 계층 제거로 오버헤드 최소화) |
| 유연성 | 낮음 (Prisma Query Engine에 강하게 종속) | 높음 (기존 pg 설정, 커넥션 옵션 그대로 활용 가능) |
1. 과거(v6 이하)
Prisma는 모든 것을 내부의 거대한 Rust Query Engine이 처리하는 블랙박스 구조로, 설치는 간단했지만 엔진이 무겁고 JS–Rust 간 통신 오버헤드로 인해 특히 서버리스 환경에서 성능 한계가 있었습니다.
2. 현재(v7.x)
Prisma는 가벼운 JavaScript/WASM 엔진이 쿼리 해석만 담당하고, 실제 DB 통신은 pg 같은 외부 드라이버에 위임하는 구조로 전환되어, 번들 크기와 오버헤드를 줄이고 성능과 유연성을 크게 개선했습니다.
🔷 실습 폴더 구조
실습의 효율성을 위해 Prisma 전용 설정을 한곳에 모으고, 각 챕터에서 이를 참조하는 구조를 사용합니다.
nodejs-tutorials/
├── node_modules/
├── prisma/
│ ├── prisma/
│ │ ├── schema.prisma <-- DB 설계도
│ │ └── migrations/ <-- DB 스키마 변경 이력(마이그레이션 파일/SQL)
│ ├── src/
│ │ ├── generated/ <-- Prisma Client 생성물(output 대상)
│ │ ├── shared/
│ │ │ └── database.ts <-- ../generated/client를 임포트
│ │ └── ch01
│ ├── .env <-- Prisma가 참조하는 환경변수
│ ├── prisma.config.ts <-- Prisma CLI 설정(프로젝트 단위)
│ ├── package.json <-- 서브프로젝트 의존성 관리
│ ├── tsconfig.json <-- 서브프로젝트 컴파일 설정 관리
├── package.json <-- 루트 프로젝트 의존성 관리
├── tsconfig.json <-- 루트 프로젝트 컴파일 설정 관리
├── eslint.config.mjs
└── .prettierrc
🔷 의존성 설치 및 초기화
# 프로젝트 폴더 이동
cd nodejs-tutorials/prisma
# 1. prisma 서브 프로젝트 생성
npm init -y
# 2. 필수 패키지 설치(TypeScript 사용, tsx 사용)
npm i -D prisma@7.1.0
npm i @prisma/client@7.1.0
# 3. PostgreSQL용 드라이버와 Prisma 어댑터 설치
npm i pg @prisma/adapter-pg
npm i -D @types/pg
▸ prisma : Prisma의 명령줄 도구(CLI) 패키지입니다.
npx prisma init
npx prisma generate
npx prisma migrate dev
npx prisma db push
npx prisma studio
▸ @prisma/client : 실제 애플리케이션 코드에서 import해서 사용하는 ORM 라이브러리입니다.
▸ pg (node-postgres) : Node.js 생태계에서 가장 검증된 PostgreSQL 통신 라이브러리입니다
▸ @prisma/adapter-pg : Prisma 전용 어댑터(브릿지)
▸ @types/pg : TypeScript 타입 정의
PS D:\NodejsDevelope\workspace\nodejs-tutorials\prisma> npm list
nodejs-tutorials@1.0.0 D:\NodejsDevelope\workspace\nodejs-tutorials
└─┬ prisma-study@1.0.0 -> .\prisma
├── @prisma/adapter-pg@7.2.0
├── @prisma/client@7.2.0
├── @types/pg@8.16.0
├── pg@8.16.3
└── prisma@7.2.0
🔷Prisma 초기화(npx prisma init)
cd nodejs-tutorials/prisma
npx prisma init
실행 후 생성되는 파일은 일반적으로 다음과 같습니다.
▸ schema.prisma : 모델/데이터소스/클라이언트 생성 설정
▸ .env : .env: 프로젝트의 데이터베이스 접속 정보를 보관합니다.
환경 변수 자동 로드를 위해 반드시 프로젝트 최상위 디렉터리(Root)에 위치해야 합니다.
▸ prisma.config.ts : Prisma CLI 설정(프로젝트 단위)

2. DB 연동 및 스키마 설계 (PostgreSQL)
🔷 .env에 PostgreSQL 연결 문자열 설정
Prisma/.env에 DATABASE_URL을 설정합니다.
DATABASE_URL="postgresql://USER:PASSWORD@localhost:5432/prisma_tutorial?schema=study"
▸ USER/PASSWORD는 본인의 로컬 PostgreSQL 계정에 맞게 변경합니다.
▸ 실습 환경에서는 데이터베이스는 prisma_tutorial, PostgreSQL 스키마는 cube를 기준으로 구성합니다.
🔷 prisma.config.ts 설정 이해
prisma.config.ts는 Prisma CLI 설정을 코드로 고정해 두는 용도입니다.
// Node.js에서 .env 파일을 읽어 process.env에 주입해 주는 코드입니다.
import "dotenv/config";
import { defineConfig, env } from "prisma/config";
export default defineConfig({
// Prisma CLI가 사용할 스키마 파일의 경로입니다.
schema: "prisma/schema.prisma",
// 마이그레이션 파일들이 저장될 경로를 지정합니다.
// migrate dev 실행 시 생성되는 SQL/메타 파일들이 이 폴더에 쌓입니다.
migrations: {
path: "prisma/migrations",
},
// Prisma CLI가 DB에 연결할 때 사용할 연결 문자열을 어디서 가져올지입니다.
datasource: {
url: env("DATABASE_URL"),
},
});
🔷 schema.prisma의 핵심 블록 이해
schema.prisma는 크게 3가지 블록으로 구성됩니다.
1. generator client : Prisma Client 생성 설정'
▸ 애플리케이션 코드에서 사용할 Prisma Client(= 타입 안전한 DB 접근 코드)를 “어떤 방식으로, 어디에 생성할지” 정합니다.
▸ Prisma는 schema.prisma를 보고 prisma.user.findMany() 같은 API를 자동으로 만들고, 그 결과물을 Prisma Client로 제공합니다.
generator client {
provider = "prisma-client" // Prisma 7부터는 -js를 뺍니다.
output = "../src/generated" // output 설정이 필수가 되었습니다.
}
| prisma-client-js | prisma-client |
| new PrismaClient() (매개변수 없음) | new PrismaClient({ adapter }) (어댑터 필수) |
| Prisma 내장 엔진 (Rust 기반 Query Engine) | 외부 JavaScript DB 드라이버 (pg, mysql2 등) |
| 코드가 간결하고 설정·관리가 편리함 | 서버 실행 속도가 빠르고 메모리 사용량이 적음 |
| 바이너리 크기가 크고 서버리스 환경에서 초기 구동이 느림 | 초기 설정 코드가 다소 복잡함 |
2. datasource db : DB 종류/연결 정보
▸ Prisma가 어떤 데이터베이스(postgresql, mysql, sqlite 등)에 연결할지를 정의합니다.
datasource db {
provider = "postgresql"
}
3. model ... : “DB 설계도” (테이블/관계/인덱스 정의)
▸ DB의 테이블 구조를 Prisma DSL로 선언하는 부분입니다.
model User {
id Int @id @default(autoincrement())
email String @unique
displayName String?
createdAt DateTime @default(now())
deletedAt DateTime? // Soft Delete용
profile Profile?
posts Post[]
likes PostLike[]
}
🔷 실습용 스키마 적용

model User {
id Int @id @default(autoincrement())
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
email String @unique
displayName String? @map("display_name")
// Relations
profile Profile?
posts Post[]
comments Comment[]
likes PostLike[]
@@index([deletedAt])
@@map("users")
}
model Profile {
id Int @id @default(autoincrement())
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
bio String?
// Relations (1:1)
userId Int @unique @map("user_id")
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([deletedAt])
@@map("profiles")
}
model Post {
id Int @id @default(autoincrement())
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
title String
content String?
published Boolean @default(false)
// Relations (N:1)
authorId Int @map("author_id")
author User @relation(fields: [authorId], references: [id], onDelete: Restrict)
comments Comment[]
likes PostLike[]
@@index([authorId, createdAt])
@@index([published, createdAt])
@@index([deletedAt])
@@map("posts")
}
model Comment {
id Int @id @default(autoincrement())
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
content String
// Relations
postId Int @map("post_id")
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
authorId Int @map("author_id")
author User @relation(fields: [authorId], references: [id], onDelete: Restrict)
@@index([postId, createdAt])
@@index([authorId, createdAt])
@@index([deletedAt])
@@map("comments")
}
model PostLike {
// Composite key (explicit M:N)
userId Int @map("user_id")
postId Int @map("post_id")
// Common-ish columns
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
deletedAt DateTime? @map("deleted_at")
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
@@id([userId, postId])
@@index([postId, createdAt])
@@index([deletedAt])
@@map("post_likes")
}
3. Prisma 설정 및 싱글톤 클라이언트 구현
🔷 DB 스키마 반영 : npx prisma migrate dev
마이그레이션 파일을 생성하며 DB 변경 이력을 남깁니다.
cd nodejs-tutorials/prisma
npx prisma migrate dev --name init
# or npx prisma migrate dev --name init --schema ./prisma/schema.prisma
▸DB와 schema는 미리 생성하는 것이 안전합니다.
✔️ npx prisma db push
- 마이그레이션 히스토리를 남기지 않고, 현재 스키마 상태를 DB에 즉시 동기화합니다.
- 빠르게 실습 진입 가능
- 운영/팀 협업에는 부적합(히스토리 추적이 약함)
cd nodejs-tutorials/prisma
npx prisma db push
# or npx prisma db push --schema ./prisma/schema.prisma
🔷 Prisma Client 생성: npx prisma generate
Prisma Client는 schema.prisma를 기반으로 타입이 포함된 클라이언트 코드를 생성합니다.
cd nodejs-tutorials/prisma
npx prisma generate
# or npx prisma generate --schema ./prisma/schema.prisma

🔷 싱글톤 Prisma Client 예시 : shared/database.ts
챕터별로 실습 파일이 나뉘어도 DB 연결은 하나의 공통 유틸로 관리하는 편이 안정적입니다.
아래는 Prisma/shared/database.ts 예시입니다.
▸ Prisma CLI의 특징: npx prisma 명령어는 기본적으로 실행 위치의 ./prisma/ 폴더나 ./ 폴더에서 .env를 자동으로 탐색합니다.
▸ Node.js의 특징: tsx나 ts-node로 코드를 실행할 때, 환경 변수 엔진은 기본적으로 프로세스가 시작된 최상위 폴더(Root)에서만 .env를 찾습니다.
import { Pool } from 'pg';
import { PrismaPg } from '@prisma/adapter-pg';
import { PrismaClient } from '../generated/client';
import * as dotenv from 'dotenv';
import * as path from 'path';
// 1. 환경 변수 로드 (Prisma 폴더 내 .env 우선 참조)
dotenv.config({ path: path.resolve(__dirname, '../.env') });
const isDev = process.env.NODE_ENV === 'development';
// 2. Global 타입 선언 (HMR 시 인스턴스 중복 생성 방지)
declare global {
var prisma: PrismaClient | undefined;
}
// 3. 인스턴스 생성 함수
function getPrismaClient() {
const connectionString = process.env.DATABASE_URL;
// PostgreSQL Pool 설정
const pool = new Pool({ connectionString });
const adapter = new PrismaPg(pool, { schema: 'study' });
// 클라이언트 생성 (개발 환경에서만 쿼리 로그 출력)
return new PrismaClient({
adapter,
log: isDev ? ['query', 'info', 'warn', 'error'] : ['error'],
});
}
// 4. 싱글톤 클라이언트 수출 (이미 있으면 재사용, 없으면 생성)
export const prisma = global.prisma || getPrismaClient();
// 개발 환경일 경우 global 객체에 할당하여 캐싱
if (isDev) global.prisma = prisma;
/**
* 5. 프로세스 종료 시 연결 해제 (Graceful Shutdown)
*/
const shutdown = async () => {
await prisma.$disconnect();
process.exit(0);
};
process.on('SIGINT', shutdown);
process.on('SIGTERM', shutdown);
✔️ dotenv의 기본 탐색 메커니즘
▸ 일반적으로 dotenv.config()를 인자 없이 호출하면, Node.js는 현재 명령어를 실행 중인 위치(.) 에서 .env 파일을 찾습니다.
▸ 만약 루트(nodejs-tutorials/)에서 npx ts-node Prisma/ch01/index.ts를 실행하면, dotenv는 nodejs-tutorials/.env를 찾으려 합니다.
▸ 하지만 실제 파일은 nodejs-tutorials/Prisma/.env에 있으므로, 아무 설정을 하지 않으면 환경 변수를 불러오지 못해 DB 연결 에러가 발생합니다.
▸ 결과적으로 path.resolve(__dirname, '../.env')를 사용하면, 서버를 어디서 실행하든 항상 Prisma/.env를 절대 경로로 추적하게 되어 설정 오류를 방지할 수 있습니다.
🔷 첫 실행 스크립트 (prisma/src/ch01/index.ts)
prisma/src/ch01/index.ts를 만들고 아래 코드를 넣습니다.
// Prisma/ch01/index.ts
import { prisma } from '../shared/database';
async function main() {
console.log('데이터 생성을 시작합니다...');
// 1. 데이터 생성 (Create)
const created = await prisma.user.create({
data: {
// @unique 제약조건 회피를 위해 타임스탬프 활용
email: `dev${Date.now()}@example.com`,
displayName: 'Prisma Dev',
// 2. 관계 생성 (Nested Write)
// User와 Profile을 하나의 트랜잭션으로 묶어 동시에 생성
profile: {
create: { bio: '안녕하세요. Prisma 학습용 프로필입니다.' },
},
},
// 3. 관계 조회 (Include)
// 반환 객체에 연관된 profile 데이터까지 포함시켜 출력
include: { profile: true },
});
// 4. 결과 확인
console.log('1) Created user:', created);
}
main()
.catch((e) => {
// 에러 발생 시 로그 출력
console.error(e);
})
.finally(async () => {
// DB 연결 종료 (프로세스 종료 전 필수)
await prisma.$disconnect();
});
# cd ./prisma
# 실행은 서브프로젝트 root에서 한다
npx tsx --env-file=./.env ./src/ch01/index.ts
▸ .env는 project root에 존재해야 하나 ./Prisma/.env에 위치하고 있어 .env위치를 지정해서 실행해야 합니다.


4. Prisma CLI 주요 명령어 요약
| 명령어 | 역할 | 사용 시점 |
| prisma init | 프로젝트 구조 생성 | Prisma 최초 도입 시 |
| format / validate | 스키마 정렬·검증 | 저장 전, CI 단계 |
| migrate dev | 로컬 DB 반영 | 모델 수정 후 |
| migrate deploy | 운영 DB 반영 | CD 파이프라인 |
| db push | 즉시 반영 | 프로토타입, MongoDB |
| generate | Client 생성 | 스키마 변경 후 |
| studio | GUI 관리 | 데이터 확인 시 |
| db pull | DB → 스키마 | 기존 DB 연동 시 |
🔷 프로젝트 초기 설정 (Setup)
- Prisma를 프로젝트에 처음 도입할 때 사용하는 단계
npx prisma init
▸ Prisma 사용을 시작하기 위한 최초 명령어
▸ prisma/schema.prisma : 모델과 DB 설정을 정의하는 핵심 파일
▸ .env : DB 연결 문자열 등 환경 변수 관리
npx prisma init
npx prisma init --datasource-provider postgresql
🔷 스키마 관리 및 검증 (Schema & Validation)
- 모델을 설계하면서 스키마의 품질과 안정성을 유지하는 단계
npx prisma format
▸ schema.prisma 파일을 자동 정렬
▸ 관계(Relation) 정의가 불완전한 경우 일부 필드를 자동 보완
npx prisma validate : CI/CD 파이프라인에서 반드시 권장
▸ 스키마 문법 오류, 관계 설정의 논리적 문제 (예: 참조 불일치)를 사전에 검사합니다.
🔷 데이터베이스 동기화 (Migration & Sync)
- Prisma 스키마와 실제 DB 상태를 맞추는 핵심 단계
npx prisma migrate dev (개발용)
▸ 스키마 변경 사항을 기반으로 SQL 마이그레이션 파일 생성, 로컬 DB에 즉시 반영
▸ Prisma Client 자동 재생성
npx prisma migrate dev
npx prisma migrate dev --name add_user_table
npx prisma migrate deploy (운영/배포용) : CI/CD 환경에서 사용
▸ 이미 생성된 마이그레이션 파일을 운영 DB에 순차적으로 적용
npx prisma db push
▸ 마이그레이션 파일을 남기지 않고 스키마를 DB에 즉시 반영
▸ 빠른 프로토타이핑
▸ MongoDB 사용 시 (마이그레이션 개념이 없음)
npx prisma db pull
▸ 이미 존재하는 DB 구조를 읽어서 schema.prisma 파일로 변환 (역공학)
▸ 기존 레거시 DB를 Prisma로 가져올 때 매우 유용합니다.
🔷 클라이언트 및 데이터 조작 (Client & Data)
- 코드에서 Prisma를 사용하기 위한 준비 및 관리 단계
npx prisma generate
▸ Prisma Client 생성
▸ TypeScript 타입 정의 포함
▸ 보통 migrate dev 시 자동 실행되지만, 수동 실행이 필요할 수 있습니다.
npx prisma studio
▸ 브라우저 기반 DB GUI 도구
▸ 데이터 조회, 수정, 삭제 가능
▸ 기본 접속 주소: http://localhost:5555
npx prisma db seed
▸ 초기 데이터(Seed) 스크립트 실행
▸ package.json에 정의된 seed 명령어를 기준으로 동작
#1. 구조 예시
project-root/
├─ prisma/
│ ├─ schema.prisma
│ └─ seed.ts
#2. package.json 설정 예시
{
"prisma": {
"seed": "tsx prisma/seed.ts"
}
}
※ 게시된 글 및 이미지 중 일부는 AI 도구의 도움을 받아 생성되거나 다듬어졌습니다.
'4.Node.js > Prisma(ORM)' 카테고리의 다른 글
| [Prisma7] 6편. Prisma로 해결되지 않는 쿼리 다루기: Raw SQL 실전 활용 (0) | 2026.01.20 |
|---|---|
| [Prisma7] 5편. Prisma 관계 조회 심화: include / select와 중첩 관계 탐색 (0) | 2026.01.19 |
| [Prisma7] 4편. 조회 쿼리 고급 옵션(where)과 관계 데이터 생성(create) 패턴 이해 (0) | 2026.01.16 |
| [Prisma7] 3편. Prisma Client Query 구조 와 CRUD API 이해하기 (0) | 2026.01.14 |
| [Prisma7] 2편. schema.prisma 설계 규칙: 필드,제약,인덱스,Relation (0) | 2026.01.13 |