๐Ÿ’ก ๊ธฐ๋ณธ ์ƒ์„ฑ

2026๋…„ 2์›” 16์ผ ์ˆ˜์ •๋จ

๐Ÿ“‹ ๊ฐœ์š”

DB ์Šคํ‚ค๋งˆ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•˜๊ณ  ์ „ํŒŒํ•˜๋Š” ์›Œํฌํ”Œ๋กœ์šฐ์ž…๋‹ˆ๋‹ค. ํŒ€ ๋‹จ์œ„ ํ˜‘์—…๊ณผ ๋ฐฐํฌ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

๐Ÿ“‹ ๋ชฉ์ฐจ

DB ์Šคํ‚ค๋งˆ๋ฅผ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณ€๊ฒฝํ•˜๊ณ  ์ „ํŒŒํ•˜๋Š” "์‹ค๋ฌด ์›Œํฌํ”Œ๋กœ์šฐ" ์ž…๋‹ˆ๋‹ค. ๋‹จ์ˆœํžˆ pushํ•˜๋Š” ๊ฒƒ์„ ๋„˜์–ด, ํŒ€ ๋‹จ์œ„ ํ˜‘์—…๊ณผ ๋ฐฐํฌ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค.


โš™๏ธ 1. Drizzle Config ์„ค์ • (์˜ต์…˜ ์ƒ์„ธ)

drizzle.config.ts ํŒŒ์ผ์€ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ๋„๊ตฌ์˜ ๊ด€์ œํƒ‘์ž…๋‹ˆ๋‹ค.

import { defineConfig } from 'drizzle-kit';
 
export default defineConfig({
  dialect: 'postgresql', // 'mysql' | 'sqlite'
  schema: './src/db/schema', // ์Šคํ‚ค๋งˆ ํŒŒ์ผ ์œ„์น˜ (๊ธ€๋กœ๋ธŒ ํŒจํ„ด ๊ฐ€๋Šฅ 'src/**/*.schema.ts')
  out: './drizzle', // ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ(.sql) ์ƒ์„ฑ ์œ„์น˜
  
  // DB ์—ฐ๊ฒฐ ์ •๋ณด (๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ์‹คํ–‰์šฉ)
  dbCredentials: {
    url: process.env.DATABASE_URL!,
  },
  
  // โญ๏ธ ์ค‘์š” ์˜ต์…˜๋“ค
  verbose: true,     // ํ„ฐ๋ฏธ๋„์— ์‹คํ–‰๋˜๋Š” SQL ์ถœ๋ ฅ
  strict: true,      // ๋ฐ์ดํ„ฐ ์†์‹ค ๊ฒฝ๊ณ  ๋ฌด์‹œ ๋ถˆ๊ฐ€ (์•ˆ์ „์žฅ์น˜)
  tablesFilter: ['!private_*'], // ํŠน์ • ํ…Œ์ด๋ธ” ๋ฌด์‹œ (์˜ˆ: Supabase ๋‚ด๋ถ€ ํ…Œ์ด๋ธ”)
});

๐Ÿ› ๏ธ 2. ํ•ต์‹ฌ ๋ช…๋ น์–ด ์ƒ์„ธ ๊ฐ€์ด๋“œ

generate (์ปค๋ฐ‹ ๋งŒ๋“ค๊ธฐ)

์Šคํ‚ค๋งˆ ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ๊ฐ์ง€ํ•ด์„œ .sql ํŒŒ์ผ์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ๋งŽ์ด ์”๋‹ˆ๋‹ค.

 
npx drizzle-kit generate
 
# โญ๏ธ ์‹๋ณ„ํ•˜๊ธฐ ์‰ฝ๊ฒŒ ์ด๋ฆ„ ๋ถ™์ด๊ธฐ (์ถ”์ฒœ)
npx drizzle-kit generate --name add_user_phone
# -> drizzle/0001_add_user_phone.sql ์ƒ์„ฑ๋จ

migrate (์ปค๋ฐ‹ ๋ฐ˜์˜ํ•˜๊ธฐ)

์ƒ์„ฑ๋œ .sql ํŒŒ์ผ๋“ค์„ ์‹ค์ œ DB์— ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

npx drizzle-kit migrate

custom (์ˆ˜๋™ SQL ์ž‘์„ฑ)

Drizzle ORM ์Šคํ‚ค๋งˆ๋กœ ํ‘œํ˜„ ๋ชปํ•˜๋Š” ๊ฒƒ๋“ค(Trigger, Stored Procedure ๋“ฑ)์„ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

# ๋นˆ ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ ์ƒ์„ฑ
npx drizzle-kit generate --custom --name create_audit_trigger

์ƒ์„ฑ๋œ ๋นˆ xxxx_create_audit_trigger.sql ํŒŒ์ผ์— ์ง์ ‘ SQL์„ ์ž‘์„ฑํ•˜๋ฉด, ๋‚˜์ค‘์— migrate ํ•  ๋•Œ ๊ฐ™์ด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.


๐Ÿšจ 3. ๋ฌธ์ œ ํ•ด๊ฒฐ (Troubleshooting)

์ƒํ™ฉ 1: Drift (ํ‘œ๋ฅ˜) ๐ŸŒŠ

"๋ˆ„๊ฐ€ ๋ชฐ๋ž˜ DB๋ฅผ ์ˆ˜์ •ํ–ˆ์–ด์š”!"
Drizzle ์Šคํ‚ค๋งˆ์™€ ์‹ค์ œ DB ์ƒํƒœ๊ฐ€ ์•ˆ ๋งž์„ ๋•Œ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. (์˜ˆ: ๋ˆ„๊ตฐ๊ฐ€ Supabase ๋Œ€์‹œ๋ณด๋“œ์—์„œ ์ง์ ‘ ์ปฌ๋Ÿผ ์ถ”๊ฐ€ํ•จ)

  1. ์ง„๋‹จ:
    npx drizzle-kit check
    # -> ์ฐจ์ด์ ์„ ๋ฆฌํฌํŠธ๋กœ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
  2. ํ•ด๊ฒฐ A (์ฝ”๋“œ ๊ธฐ์ค€ ๋™๊ธฐํ™”):
    ๋‹ค์‹œ push ํ•˜๊ฑฐ๋‚˜ generateํ•ด์„œ DB๋ฅผ ๋‚ด ์ฝ”๋“œ์— ๋งž์ถฅ๋‹ˆ๋‹ค. (DB ๋ณ€๊ฒฝ์‚ฌํ•ญ ๋ฎ์–ด์”€)
  3. ํ•ด๊ฒฐ B (DB ๊ธฐ์ค€ ๋™๊ธฐํ™”):
    introspect (๋˜๋Š” pull) ๋ช…๋ น์–ด๋กœ DB ์ƒํƒœ๋ฅผ ์Šคํ‚ค๋งˆ ํŒŒ์ผ๋กœ ์—ญ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
    npx drizzle-kit pull

์ƒํ™ฉ 2: ์ถฉ๋Œ (Conflicts) โš”๏ธ

๋™๋ฃŒ A์™€ B๊ฐ€ ๋™์‹œ์— ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜ ํŒŒ์ผ์„ ๋งŒ๋“ค์–ด์„œ ์ปค๋ฐ‹ํ–ˆ์Šต๋‹ˆ๋‹ค.

  • 0005_add_post.sql (A)
  • 0005_add_comment.sql (B)
    ์ˆœ์„œ ๋ฒˆํ˜ธ๊ฐ€ ๊ฒน์ณค๋„ค์š”!

ํ•ด๊ฒฐ:

  1. ํŒŒ์ผ ์ด๋ฆ„์˜ ์ˆซ์ž๋ฅผ ์ˆ˜์ •ํ•˜๊ฑฐ๋‚˜ (์ˆ˜๋™)
  2. ๊ฐ€์žฅ ์ตœ์‹  ์Šค๋ƒ…์ƒท์„ ์‚ญ์ œํ•˜๊ณ  ๋‹ค์‹œ generate ํ•ฉ๋‹ˆ๋‹ค.
  3. Drizzle Kit์ด ์•Œ์•„์„œ ์ˆœ์„œ๋ฅผ ์žฌ์กฐ์ •ํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. (๋ฒ„์ „์—…๋˜๋ฉด์„œ ๋˜‘๋˜‘ํ•ด์ง)

๐Ÿš€ 4. ๋ฐฐํฌ ์ „๋žต (Production Deployment)

์•ˆ์ „ํ•œ ๋ฐฐํฌ ์น˜ํŠธ์‹œํŠธ CheckList โœ…

  1. Schema Sync: ๋กœ์ปฌ์—์„œ drizzle-kit generate ์™„๋ฃŒ ํ›„ ์ปค๋ฐ‹.
  2. Dry Run: ์‹ค์ œ ๋ฐฐํฌ ์ „ ํ…Œ์ŠคํŠธ DB์— ๋จผ์ € ์ ์šฉํ•ด๋ด„.
  3. Backup: (์šด์˜ ํ™˜๊ฒฝ) ๋ฐฐํฌ ์ง์ „ ์Šค๋ƒ…์ƒท/๋ฐฑ์—… ํ•„์ˆ˜.
  4. Auto Migrate: ์„œ๋ฒ„ ์‹œ์ž‘ ์‹œ ์Šคํฌ๋ฆฝํŠธ๋กœ ์ž๋™ ์‹คํ–‰.

NestJS ๋“ฑ ์„œ๋ฒ„ ์ฝ”๋“œ์—์„œ ์ž๋™ ์‹คํ–‰ํ•˜๊ธฐ:

// src/db/migrate.ts
import { migrate } from 'drizzle-orm/postgres-js/migrator';
import { db } from './index';
 
async function main() {
  console.log('Migrating...');
  // 'drizzle' ํด๋”์˜ sql ํŒŒ์ผ๋“ค์„ ์ฝ์–ด์„œ ์‹คํ–‰
  await migrate(db, { migrationsFolder: './drizzle' });
  console.log('Done!');
}
main();

์ฃผ์˜: ์„œ๋ฒ„ ์ธ์Šคํ„ด์Šค๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ(PM2 ํด๋Ÿฌ์Šคํ„ฐ, K8s ํŒŒ๋“œ ๋“ฑ)์ผ ๋•Œ, ๋™์‹œ์— migrate๊ฐ€ ์‹คํ–‰๋˜๋ฉด ๋ฝ(Lock) ๊ฑธ๋ฆฌ๊ฑฐ๋‚˜ ๊ผฌ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐฐํฌ ํŒŒ์ดํ”„๋ผ์ธ(CI/CD)์˜ ๋ณ„๋„ ๋‹จ๊ณ„ ๋กœ ๋นผ๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.


๐Ÿ”— ๋ ˆํผ๋Ÿฐ์Šค

๋‹ค์Œ ์žฅ: 05. CRUD ์กฐ์ž‘ (CRUD Operations)