npm install @auth/prisma-adapter @prisma/client
prisma-adapter, prisma/client를 설치
아래 명령어로 초기화를 진행
npx prisma init
.env에 DATABASE_URL 구성 아래는 예시
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
prisma init을 통해 생기는 prisma/schema.prisma에 아래와 같이 구성
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
DB에 이미 사용중인 table이 있다면 pull 을 통해 schema.prisma 파일에 불러올 수 있다.
npx prisma db pull
Table 생성
schema.prisma에 model을 기재하고 table을 생성할 수 있다.
예시)
model auth_user {
id Int @id @default(autoincrement())
email String @unique
email_verified DateTime?
name String?
image String?
hashed_password String? // Optional because OAuth users won't have passwords
created_at DateTime @default(now())
updated_at DateTime @updatedAt
// Relations
social_logins auth_social_login[]
refresh_tokens auth_refresh_token[]
}
Prisma는 Schema 외에 코드상으로 구현된 테이블 구조를 참조하므로 Schema를 불러오거나 생성했다면 아래 명령어를 실행
npx prisma generate
schma를 통해 table을 생성
npx prisma migrate dev --name description
코드로 작성한 table들이 만들어지고, _prisma_migrations 라는 테이블도 같이 생성되며 description은 어떤 migration을 한건지 서술하는 역할을 한다.
** 개발 단계에서는 위 명령어를 사용하면 되는데, 기존에 table에 자료가 있는데 위 명령어를 실행하면 데이터가 다 날라가는 불상사를 겪게 된다.
DB 백업을 우선적으로 하도록 하자.
** 개발환경과 프로덕션 환경에 따라서 다르게 할 수 있다.
프로덕션 환경에서는 더욱 조심해야하므로 'npx prisma migrate deploy'를 활용하도록 하자.
어떠한 차이가 있는지는 글 아래에 Claude 질문/답변 내용을 첨부한다.
코드상에서 prisma를 사용하기 위해 @prisma/client의 PrismaClient 객체를 통해 접근
예시 코드
// lib/database/prisma.ts
import { PrismaClient } from '@prisma/client'
const globalForPrisma = globalThis as unknown as {
prisma: PrismaClient | undefined
}
export const prisma = globalForPrisma.prisma ?? new PrismaClient()
if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma
위의 prisma client를 통해서 아래와 같이 회원가입 api를 구성할 수 있다.
import { NextResponse } from 'next/server'
import { hash } from 'bcryptjs'
import { prisma } from '@/lib/database/prisma'
export async function POST(req: Request) {
try {
const { email, password, passwordConfirm } = await req.json()
// Validate input
if (!email || !password || !passwordConfirm) {
return NextResponse.json(
{ error: 'Missing required fields' },
{ status: 400 }
)
}
// Check if user already exists
const existingUser = await prisma.auth_user.findUnique({
where: { email }
})
if (existingUser) {
return NextResponse.json(
{ error: 'User already exists' },
{ status: 400 }
)
}
// Check if password and passwordConfirm match
if (password !== passwordConfirm) {
return NextResponse.json(
{ error: 'Passwords do not match' },
{ status: 400 }
)
}
// Hash password
const hashedPassword = await hash(password, 12)
// Create user
const user = await prisma.auth_user.create({
data: {
email,
hashed_password: hashedPassword
}
})
// Remove password from response
return NextResponse.json({
success: true,
user: {
id: user.id,
email: user.email,
}
})
} catch (error) {
console.error(error);
return NextResponse.json(
{ error: 'Error creating user' },
{ status: 500 }
)
}
}
1. npx prisma migrate dev vs 2. npx prisma migrate deploy
1. npx prisma migrate dev --name add_user_table
- Used in development environment
- Creates new migration files
- Applies pending migrations
- Resets database if needed
- Regenerates Prisma Client
- Can detect schema changes
- Interactive (asks questions)
- Can reset database if schema drift detected
Example workflow:
# 1. Change schema.prisma
model User {
id Int @id @default(autoincrement())
email String @unique
}
# 2. Create and apply migration
npx prisma migrate dev --name add_user_table
# Result:
# - Creates migration file in prisma/migrations
# - Applies migration to database
# - Regenerates Prisma Client
2. npx prisma migrate deploy
- Used in production environment
- Only applies pending migrations
- Never creates new migrations
- Never resets database
- Non-interactive (safe for CI/CD)
- Doesn't regenerate Prisma Client
- Throws error if schema drift detected
Example workflow:
# Production deployment script
npm install
npx prisma generate # Generate Prisma Client
npx prisma migrate deploy # Apply pending migrations
npm run build
npm start
Quick Reference: