Drizzle λ§μ΄κ·Έλ μ΄μ
κΈ°μ΄
SQL λ°μ΄ν°λ² μ΄μ€λ μ μ₯ν μν°ν°μ μ격ν μ€ν€λ§λ₯Ό μ¬μ μ μ§μ ν΄μΌ νλ©°,
μ΄λ¬ν μν°ν°μ ννλ₯Ό λ³κ²½ν΄μΌ ν λλ μ€ν€λ§ λ§μ΄κ·Έλ μ΄μ
μ ν΅ν΄ μνν΄μΌ ν©λλ€.
λ°μ΄ν°λ² μ΄μ€ λ§μ΄κ·Έλ μ΄μ
μ κ΄λ¦¬νλ μ¬λ¬ νλ‘λμ
μμ€μ λ°©λ²μ΄ μμ΅λλ€.
Drizzleμ λ°μ΄ν°λ² μ΄μ€ μ°μ λλ μ½λλ² μ΄μ€ μ°μ λ°©μμ κ΄κ³μμ΄ λͺ¨λ λ°©λ²μ μλ²½νκ² μ ν©νλλ‘ μ€κ³λμμ΅λλ€.
λ°μ΄ν°λ² μ΄μ€ μ°μ μ λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§κ° μ λ’°ν μ μλ μμ€μΈ κ²½μ°μ
λλ€. λ°μ΄ν°λ² μ΄μ€μμ μ§μ λλ
λ°μ΄ν°λ² μ΄μ€ λ§μ΄κ·Έλ μ΄μ
λꡬλ₯Ό ν΅ν΄ λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§λ₯Ό κ΄λ¦¬ν λ€μ, λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§λ₯Ό μ½λλ² μ΄μ€ μ ν리μΌμ΄μ
μμ€ μν°ν°λ‘ κ°μ Έμ΅λλ€.
μ½λλ² μ΄μ€ μ°μ μ μ½λλ² μ΄μ€μ λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§κ° μ λ’°ν μ μλ μμ€μ΄λ©° λ²μ κ΄λ¦¬ νμ μλ κ²½μ°μ
λλ€. JavaScript/TypeScriptλ‘ λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§λ₯Ό μ μΈνκ³ κ΄λ¦¬ν λ€μ,
Drizzleμ ν΅ν΄ μ§μ λλ μΈλΆ λ§μ΄κ·Έλ μ΄μ
λꡬλ₯Ό ν΅ν΄ ν΄λΉ μ€ν€λ§λ₯Ό λ°μ΄ν°λ² μ΄μ€ μ체μ μ μ©ν©λλ€.
Drizzleμ΄ μ΄λ»κ² λμΈ μ μλμ?
Drizzleκ³Ό ν¨κ» λ§μ΄κ·Έλ μ΄μ
μ κ΄λ¦¬νκΈ° μν CLI μ±μΈ drizzle-kitμ ꡬμΆνμ΅λλ€.
drizzle-kit migrate
drizzle-kit generate
drizzle-kit push
drizzle-kit pull
νμ¬ λΉμ¦λμ€ μꡬμ¬νμ λ°λΌ λ§μ΄κ·Έλ μ΄μ
μ κ·Ό λ°©μμ μ νν μ μλλ‘ μ€κ³λμμ΅λλ€.
λ°μ΄ν°λ² μ΄μ€ μ°μ κ³Ό μ½λλ² μ΄μ€ μ°μ μ κ·Ό λ°©μ λͺ¨λμ μ ν©νλ©°, μ€ν€λ§λ₯Ό νΈμνκ±°λ SQL λ§μ΄κ·Έλ μ΄μ
νμΌμ μμ±νκ±°λ λ°μ΄ν°λ² μ΄μ€μμ μ€ν€λ§λ₯Ό κ°μ Έμ¬ μ μμ΅λλ€.
νΌμ μμ
νλ νμΌλ‘ μμ
νλ μλ²½ν©λλ€.
μ΄μ νλ‘μ νΈμ κ°μ₯ μ ν©ν μ΅μ
μ μ νν΄ λ³΄κ² μ΅λλ€:
μ΅μ
1
μΈλΆ λ§μ΄κ·Έλ μ΄μ
λꡬλ₯Ό μ¬μ©νκ±°λ λ°μ΄ν°λ² μ΄μ€μμ μ§μ SQL λ§μ΄κ·Έλ μ΄μ
μ μ€ννμ¬ λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§λ₯Ό μ§μ κ΄λ¦¬ν©λλ€.
Drizzleμμλ λ°μ΄ν°λ² μ΄μ€μμ μ€ν€λ§μ νμ¬ μνλ₯Ό κ°μ Έμ TypeScript μ€ν€λ§ νμΌλ‘ μ μ₯νκΈ°λ§ νλ©΄ λ©λλ€.
μ΄κ²μ λ°μ΄ν°λ² μ΄μ€ μ°μ μ κ·Ό λ°©μμ
λλ€. λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§λ₯Ό μ λ’°ν μ μλ μμ€λ‘ μ¬μ©νλ©°,
Drizzleμ drizzle-kit pull λͺ
λ Ήμ μ¬μ©νμ¬ λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§λ₯Ό TypeScriptλ‘ κ°μ Έμ¬ μ μκ² ν΄μ€λλ€.
ββββββββββββββββββββββββββ βββββββββββββββββββββββββββ
β β <--- CREATE TABLE "users" (
ββββββββββββββββββββββββββββ β β "id" SERIAL PRIMARY KEY,
β ~ drizzle-kit pull β β β "name" TEXT,
βββ¬βββββββββββββββββββββββββ β DATABASE β "email" TEXT UNIQUE
β β β );
β Pull datatabase schema -----> β β
β Generate Drizzle <----- β β
β schema TypeScript file ββββββββββββββββββββββββββ
β
v
import * as p from "drizzle-orm/pg-core";
export const users = p.pgTable("users", {
id: p.serial().primaryKey(),
name: p.text(),
email: p.text().unique(),
});
μ΅μ
2
TypeScript μ½λλ² μ΄μ€μ λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§λ₯Ό λκ³ μΆκ³ ,
SQL λ§μ΄κ·Έλ μ΄μ
νμΌμ λ€λ£¨κ³ μΆμ§ μμ΅λλ€.
Drizzleμ΄ λ΄ μ€ν€λ§λ₯Ό λ°μ΄ν°λ² μ΄μ€μ μ§μ βνΈμβνκΈ°λ₯Ό μν©λλ€.
μ΄κ²μ μ½λλ² μ΄μ€ μ°μ μ κ·Ό λ°©μμ
λλ€. TypeScript Drizzle μ€ν€λ§λ₯Ό μ λ’°ν μ μλ μμ€λ‘ μ¬μ©νλ©°,
Drizzleμ drizzle-kit push λͺ
λ Ήμ μ¬μ©νμ¬ μ€ν€λ§ λ³κ²½ μ¬νμ λ°μ΄ν°λ² μ΄μ€μ νΈμν μ μκ² ν΄μ€λλ€.
μ΄κ²μ λΉ λ₯Έ νλ‘ν νμ΄νμ κ°μ₯ μ ν©ν μ κ·Ό λ°©μμ΄λ©°, μμ κ°μ νκ³Ό
κ°μΈ κ°λ°μλ€μ΄ νλ‘λμ
μ ν리μΌμ΄μ
μμ μ£Όμ λ§μ΄κ·Έλ μ΄μ
νλ¦μΌλ‘ μ±κ³΅μ μΌλ‘ μ¬μ©νλ κ²μ 보μμ΅λλ€.
import * as p from "drizzle-orm/pg-core";
export const users = p.pgTable("users", {
id: p.serial().primaryKey(),
name: p.text(),
email: p.text().unique(), // <--- added column
});
Add column to `users` table
ββββββββββββββββββββββββββββ
β + email: text().unique() β
βββ¬βββββββββββββββββββββββββ
β
v
ββββββββββββββββββββββββββββ
β ~ drizzle-kit push β
βββ¬βββββββββββββββββββββββββ
β ββββββββββββββββββββββββββββ
β Pull current datatabase schema ---------> β β
β β
β Generate alternations based on diff <---- β DATABASE β
β β β
β Apply migrations to the database -------> β β
β ββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββββββββββ΄βββββββββββββββ
ALTER TABLE `users` ADD COLUMN `email` TEXT UNIQUE;
μ΅μ
3
TypeScript μ½λλ² μ΄μ€μ λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§λ₯Ό λκ³ μΆκ³ ,
Drizzleμ΄ SQL λ§μ΄κ·Έλ μ΄μ
νμΌμ μμ±νκ³ λ°μ΄ν°λ² μ΄μ€μ μ μ©νκΈ°λ₯Ό μν©λλ€.
μ΄κ²μ μ½λλ² μ΄μ€ μ°μ μ κ·Ό λ°©μμ
λλ€. TypeScript Drizzle μ€ν€λ§λ₯Ό μ λ’°ν μ μλ μμ€λ‘ μ¬μ©νλ©°,
Drizzleμ drizzle-kit generate λͺ
λ ΉμΌλ‘ μ€ν€λ§ λ³κ²½ μ¬νμ κΈ°λ°μΌλ‘ SQL λ§μ΄κ·Έλ μ΄μ
νμΌμ μμ±νκ³ ,
drizzle-kit migrate λͺ
λ ΉμΌλ‘ λ°μ΄ν°λ² μ΄μ€μ μ μ©ν μ μκ² ν΄μ€λλ€.
import * as p from "drizzle-orm/pg-core";
export const users = p.pgTable("users", {
id: p.serial().primaryKey(),
name: p.text(),
email: p.text().unique(),
});
ββββββββββββββββββββββββββ
β $ drizzle-kit generate β
βββ¬βββββββββββββββββββββββ
β
β 1. read previous migration folders
2. find diff between current and previous schema
3. prompt developer for renames if necessary
β 4. generate SQL migration and persist to file
β βββ΄ββββββββββββββββββββββββββββββββββββββββ
β π drizzle
β β π 20242409125510_premium_mister_fear
β β π snapshot.json
β β π migration.sql
v
-- drizzle/20242409125510_premium_mister_fear/migration.sql
CREATE TABLE "users" (
"id" SERIAL PRIMARY KEY,
"name" TEXT,
"email" TEXT UNIQUE
);
βββββββββββββββββββββββββ
β $ drizzle-kit migrate β
βββ¬ββββββββββββββββββββββ
β ββββββββββββββββββββββββββββ
β 1. read migration.sql files in migrations folder β β
2. fetch migration history from database -------------> β β
β 3. pick previously unapplied migrations <-------------- β DATABASE β
β 4. apply new migration to the database ---------------> β β
β β
ββββββββββββββββββββββββββββ
[β] done!
μ΅μ
4
TypeScript μ½λλ² μ΄μ€μ λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§λ₯Ό λκ³ μΆκ³ ,
Drizzleμ΄ SQL λ§μ΄κ·Έλ μ΄μ
νμΌμ μμ±νκ³ λ°νμμ μ μ©νκΈ°λ₯Ό μν©λλ€.
μ΄κ²μ μ½λλ² μ΄μ€ μ°μ μ κ·Ό λ°©μμ
λλ€. TypeScript Drizzle μ€ν€λ§λ₯Ό μ λ’°ν μ μλ μμ€λ‘ μ¬μ©νλ©°,
Drizzleμ drizzle-kit generate λͺ
λ ΉμΌλ‘ μ€ν€λ§ λ³κ²½ μ¬νμ κΈ°λ°μΌλ‘ SQL λ§μ΄κ·Έλ μ΄μ
νμΌμ μμ±νκ³ ,
μ ν리μΌμ΄μ
λ°νμ λμ λ°μ΄ν°λ² μ΄μ€μ μ μ©ν μ μμ΅λλ€.
μ΄ μ κ·Ό λ°©μμ 무μ€λ¨ λ°°ν¬ μ€μ λ°μ΄ν°λ² μ΄μ€ λ§μ΄κ·Έλ μ΄μ
μ μ μ©νκ³
λ¬Έμ κ° λ°μνλ©΄ DDL λ³κ²½ μ¬νμ λ‘€λ°±νλ λͺ¨λ리μ μ ν리μΌμ΄μ
μ λ리 μ¬μ©λ©λλ€.
λ°°ν¬ νλ‘μΈμ€ μ€μ 컀μ€ν
리μμ€μμ ν λ² μ€νλλ λ§μ΄κ·Έλ μ΄μ
κ³Ό ν¨κ» μλ²λ¦¬μ€ λ°°ν¬μμλ μ¬μ©λ©λλ€.
import * as p from "drizzle-orm/pg-core";
export const users = p.pgTable("users", {
id: p.serial().primaryKey(),
name: p.text(),
email: p.text().unique(),
});
ββββββββββββββββββββββββββ
β $ drizzle-kit generate β
βββ¬βββββββββββββββββββββββ
β
β 1. read previous migration folders
2. find diff between current and previous schema
3. prompt developer for renames if necessary
β 4. generate SQL migration and persist to file
β βββ΄ββββββββββββββββββββββββββββββββββββββββ
β π drizzle
β β π 20242409125510_premium_mister_fear
β β π snapshot.json
β β π migration.sql
v
-- drizzle/20242409125510_premium_mister_fear/migration.sql
CREATE TABLE "users" (
"id" SERIAL PRIMARY KEY,
"name" TEXT,
"email" TEXT UNIQUE
);
// index.ts
import { drizzle } from "drizzle-orm/node-postgres"
import { migrate } from 'drizzle-orm/node-postgres/migrator';
const db = drizzle(process.env.DATABASE_URL);
await migrate(db);
βββββββββββββββββββββββββ
β npx tsx src/index.ts β
βββ¬ββββββββββββββββββββββ
β
β 1. init database connection ββββββββββββββββββββββββββββ
β 2. read migration.sql files in migrations folder β β
3. fetch migration history from database -------------> β β
β 4. pick previously unapplied migrations <-------------- β DATABASE β
β 5. apply new migration to the database ---------------> β β
β β
ββββββββββββββββββββββββββββ
[β] done!
μ΅μ
5
TypeScript μ½λλ² μ΄μ€μ λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§λ₯Ό λκ³ μΆκ³ ,
Drizzleμ΄ SQL λ§μ΄κ·Έλ μ΄μ
νμΌμ μμ±νκΈ°λ₯Ό μνμ§λ§,
λ°μ΄ν°λ² μ΄μ€μ μ§μ λλ μΈλΆ λ§μ΄κ·Έλ μ΄μ
λꡬλ₯Ό ν΅ν΄ μ μ©νκ² μ΅λλ€.
μ΄κ²μ μ½λλ² μ΄μ€ μ°μ μ κ·Ό λ°©μμ
λλ€. TypeScript Drizzle μ€ν€λ§λ₯Ό μ λ’°ν μ μλ μμ€λ‘ μ¬μ©νλ©°,
Drizzleμ drizzle-kit generate λͺ
λ ΉμΌλ‘ μ€ν€λ§ λ³κ²½ μ¬νμ κΈ°λ°μΌλ‘ SQL λ§μ΄κ·Έλ μ΄μ
νμΌμ μμ±νκ³ ,
λ°μ΄ν°λ² μ΄μ€μ μ§μ λλ μΈλΆ λ§μ΄κ·Έλ μ΄μ
λꡬλ₯Ό ν΅ν΄ μ μ©ν μ μμ΅λλ€.
import * as p from "drizzle-orm/pg-core";
export const users = p.pgTable("users", {
id: p.serial().primaryKey(),
name: p.text(),
email: p.text().unique(),
});
ββββββββββββββββββββββββββ
β $ drizzle-kit generate β
βββ¬βββββββββββββββββββββββ
β
β 1. read previous migration folders
2. find diff between current and previous scheama
3. prompt developer for renames if necessary
β 4. generate SQL migration and persist to file
β βββ΄ββββββββββββββββββββββββββββββββββββββββ
β π drizzle
β β π 20242409125510_premium_mister_fear
β β π snapshot.json
β β π migration.sql
v
-- drizzle/20242409125510_premium_mister_fear/migration.sql
CREATE TABLE "users" (
"id" SERIAL PRIMARY KEY,
"name" TEXT,
"email" TEXT UNIQUE
);
βββββββββββββββββββββββββββββββββββββ
β (._.) now you run your migrations β
βββ¬ββββββββββββββββββββββββββββββββββ
β
directly to the database
β ββββββββββββββββββββββ
ββββββββββββββββββββββββββββββββββββββ¬βββ>β β
β β β Database β
or via external tools β β β
β β ββββββββββββββββββββββ
β ββββββββββββββββββββββ β
ββββ Bytebase ββββββββββββββ
ββββββββββββββββββββββ€
β Liquibase β
ββββββββββββββββββββββ€
β Atlas β
ββββββββββββββββββββββ€
β etcβ¦ β
ββββββββββββββββββββββ
[β] done!
μ΅μ
6
TypeScript μ½λλ² μ΄μ€μ λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§λ₯Ό λκ³ μΆκ³ ,
Drizzleμ΄ Drizzle μ€ν€λ§μ SQL ννμ μ½μμ μΆλ ₯νκΈ°λ₯Ό μνλ©°,
Atlasλ₯Ό ν΅ν΄ λ°μ΄ν°λ² μ΄μ€μ μ μ©νκ² μ΅λλ€.
μ΄κ²μ μ½λλ² μ΄μ€ μ°μ μ κ·Ό λ°©μμ
λλ€. TypeScript Drizzle μ€ν€λ§λ₯Ό μ λ’°ν μ μλ μμ€λ‘ μ¬μ©νλ©°,
Drizzleμ drizzle-kit export λͺ
λ ΉμΌλ‘ μ€ν€λ§ λ³κ²½ μ¬νμ κΈ°λ°μΌλ‘ SQL λ¬Έμ λ΄λ³΄λ΄κ³ ,
Atlas λλ κΈ°ν μΈλΆ SQL λ§μ΄κ·Έλ μ΄μ
λꡬλ₯Ό ν΅ν΄ λ°μ΄ν°λ² μ΄μ€μ μ μ©ν μ μμ΅λλ€.
import * as p from "drizzle-orm/pg-core";
export const users = p.pgTable("users", {
id: p.serial().primaryKey(),
name: p.text(),
email: p.text().unique(),
});
ββββββββββββββββββββββββββ
β $ drizzle-kit export β
βββ¬βββββββββββββββββββββββ
β
β 1. read your drizzle schema
2. generated SQL representation of your schema
β 3. outputs to console
β
β
v
CREATE TABLE "users" (
"id" SERIAL PRIMARY KEY,
"name" TEXT,
"email" TEXT UNIQUE
);
βββββββββββββββββββββββββββββββββββββ
β (._.) now you run your migrations β
βββ¬ββββββββββββββββββββββββββββββββββ
β
via Atlas
β ββββββββββββββββ
β ββββββββββββββββββββββ β β
ββββ Atlas ββββββββββββ>β Database β
ββββββββββββββββββββββ β β
ββββββββββββββββ
[β] done!