Prisma에서 Down Migration을 생성해보자

윤학·2024년 10월 1일
0

Prisma

목록 보기
3/3
post-thumbnail

이번 글에서는 Prisma에서 Schema 변경 후 다시 이전 상태의 Schema로 돌아갈 수 있는 Down Migration을 생성해 보려 한다.

Prisma에서는 Schema 변경 후 Migration 파일을 생성할 때 자동으로 Down Migration을 생성해 주지 않으므로 별도로 생성해야 한다.

만약 생성된 Migration에서 데이터를 옮기거나 추가적인 SQL문을 작성하는 부분이 있으면 해당 부분까지는 생성해 주지 않지만, 이전 Schema로 돌아갈 수 있게 해주므로 안전한 기능이라고 생각한다.

그럼 한 단계씩 살펴보자.

Prisma에 대한 기본 세팅은 해당 글에서는 다루지 않습니다.

먼저, Schema 파일에 User와 Cart를 정의해 보자.

Schema 정의

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model User {
  id            Int     	@id @default(autoincrement())
  name          String  
  phoneNumber   String  	@map("phone_number")
  cart          Cart?
  createdAt     DateTime    @default(now()) @map("created_at")
  updatedAt     DateTime    @updatedAt @map("updated_at")

  @@map("user")
}

model Cart {
  id      	Int     	@id @default(autoincrement())
  userId  	Int     	@unique @map("user_id")
  createdAt DateTime  	@default(now()) @map("created_at")
  updatedAt DateTime  	@updatedAt @map("updated_at")

  user    	User    	@relation(fields: [userId], references: [id])
  
  @@map("cart")
}

그리고 Migration 파일을 하나 만들어줘야 하는데,

그전에 Test DB 하나를 띄워보자. (해당 글에서는 docker compose)

name: test-db

services:
  postgresql:
    container_name: test-postgresql
    image: postgres
    ports:
      - "5432:5432"
    environment:
      POSTGRES_PASSWORD: test1234
      POSTGRES_DB: test

그리고 npx prisma migrate dev를 입력하여 Migration 파일을 만든다.

생성된 Migration 파일을 살펴보면 알맞게 생성이 된 것으로 볼 수 있다.

-- CreateTable
CREATE TABLE "user" (
    "id" SERIAL NOT NULL,
    "name" TEXT NOT NULL,
    "phone_number" TEXT NOT NULL,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updated_at" TIMESTAMP(3) NOT NULL,

    CONSTRAINT "user_pkey" PRIMARY KEY ("id")
);

-- CreateTable
CREATE TABLE "cart" (
    "id" SERIAL NOT NULL,
    "user_id" INTEGER NOT NULL,
    "created_at" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
    "updated_at" TIMESTAMP(3) NOT NULL,

    CONSTRAINT "cart_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "cart_user_id_key" ON "cart"("user_id");

-- AddForeignKey
ALTER TABLE "cart" ADD CONSTRAINT "cart_user_id_fkey" FOREIGN KEY ("user_id") REFERENCES "user"("id") ON DELETE RESTRICT ON UPDATE CASCADE;

Migration 파일 하나지만 여기까지 개발했다고 치고, 새로운 User 테이블에 email 컬럼과 추가로 Post 테이블을 추가해 보자.

Down Migration 생성

model User {
  id            Int         @id @default(autoincrement())
  name          String  
  phoneNumber   String      @map("phone_number")
  email         String		<----------추가

  cart          Cart?
  createdAt     DateTime    @default(now()) @map("created_at")
  updatedAt     DateTime    @updatedAt @map("updated_at")

  posts         Post[]

  @@map("user")
}

model Post {				<----------추가
  id          Int         @id @default(autoincrement())
  userId      Int
  user        User        @relation(fields: [userId], references: [id])
}

model Cart {
  id      Int     @id @default(autoincrement())
  userId  Int     @unique @map("user_id")
  createdAt DateTime  @default(now()) @map("created_at")
  updatedAt DateTime  @updatedAt @map("updated_at")

  user    User    @relation(fields: [userId], references: [id])
  
  @@map("cart")
}

Down Migration 파일은 새로운 Schema가 반영되는 Migration 파일을 생성하기 전에 미리 생성을 해놓아야 한다.

왜냐하면 Down Migration은 지금까지의 Migration history와 위에 작성된 최신 Schema를 비교해서 생성되기 때문이다.

해당 시점에서는 Migration history가 최신 Schema를 작성하기 전까지의 기록이므로

그리고 migrate diff를 통해 생성해보자.

npx prisma migrate diff \                                                                     
--from-schema-datamodel prisma/schema.prisma \
--to-migrations prisma/migrations \
--shadow-database-url ${SHADOW_DATABASE_URL}/shadow_test \
--script > down.sql

여기서 옵션들을 잠깐 살펴보면

  • --to-migrations: 이 옵션은 위에서 작성한 최신 Schema와 prisma/migrations 폴더에 있는 Migration history를 비교해서 Down Migration을 생성한다.
    이 옵션을 사용하려면 ShadowDatabase가 꼭 필요하기에 --shadow-database-url 옵션을 함께 사용해야 한다.
  • --shadow-database-url: prisma/migrations 폴더에 있는 Migration history들을 전부 Shadown database에 적용시켜 보고 schema.prisma에 있는 최신 Schema와 비교하는 용도로 사용할 임시 데이터베이스로 사용할 url을 지정해 주면 된다.
    말 그대로 임시 데이터베이스이기 때문에 사용할 DB url과 동일하게 입력하면 DB가 삭제될 수 있기에 꼭 다르게 해야한다.
    --script: 생성되는 SQL 스크립트를 down.sql파일로 출력한다.

만약 Shadow Database를 사용하지 않으려면 아래와 같은 다른 대안이 있으나, 해당 글에서는 위의 방법으로 진행해 보자.

npx prisma migrate diff \
--from-schema-datamodel prisma/schema.prisma \
--to-schema-datasource prisma/schema.prisma \
--script > down.sql

Shadow Database를 위해 추가 DB를 작성하고, 해당 url을 작성해보자.

name: test-db-setup

services:
  postgresql:
    container_name: test-postgresql
    image: postgres
    ports:
      - "5432:5432"
    environment:
      POSTGRES_PASSWORD: test1234
      POSTGRES_DB: test
  shadow-postgresql:
    container_name: shadow-postgresql
    image: postgres
    command: -p 5433
    ports:
      - "5433:5433"
    environment:
      POSTGRES_PASSWORD: test1234
      POSTGRES_DB: shadow_test
npx prisma migrate diff \                                                                     
--from-schema-datamodel prisma/schema.prisma \
--to-migrations prisma/migrations \
--shadow-database-url postgresql://postgres:test1234@localhost:5433/shadow_test \
--script > down.sql

그리고 프로젝트 루트위치에 생성되는 down.sql 파일에 알맞게 작성됐는지 확인한다.

-- DropForeignKey
ALTER TABLE "Post" DROP CONSTRAINT "Post_userId_fkey";

-- AlterTable
ALTER TABLE "user" DROP COLUMN "email";

-- DropTable
DROP TABLE "Post";

Down Migration 파일도 생성했으니 먼저 변경된 Schema를 반영해보자.

Down Migration 적용

이제 생성해놨던 down.sql 파일을 db execute를 통해 db에 실행시켜보자.
file의 위치와 schema의 위치는 다른곳에 저장해두었으면 해당 위치를 작성하면 된다.

prisma 문서에는 이후 단계로 migrate resolve를 통해 해당 Migration이 롤백 후 해결된 상태로 표시하는 단계를 알려주고 있다.

만약 Migration 과정 중 오류가 나서 실패한 경우라면 해당 과정을 수행하면 되지만,
성공적으로 Migration이 수행됐는데 다시 돌아가고 싶은 경우라면 Migration이 실패한 상태가 아니기에 해당 과정은 오류가 난다.

참고

Generating down migrations
About the shadow database

0개의 댓글