저장을 습관화

NestJS TypeORM 연습 기록 - migrations 본문

공부/node.js

NestJS TypeORM 연습 기록 - migrations

ctrs 2023. 11. 12. 18:15

사용하는 이유

예를 들어 mysql workbench에서 SQL 명령어를 직접 입력하여

테이블의 컬럼명을 바꾸었다고 해보자.

 

이 작업은 DB 테이블 내에서만 적용하는 것이 아니라

개발 중인 프로젝트의 entities에서도 적용해주어야한다.

 

DB 테이블에만 적용하고 entitiy를 적용하지 않았거나, 작업 중 실수로 잘못된 값을 입력하여

entities와 DB의 내용이 서로 다를 경우 불일치 에러가 발생할 수 있다.

 

0. package.json

지난 시간에 작성했던 내용 중

https://ctrs.tistory.com/467

 

NestJS TypeORM 연습 기록 - DB 생성, 테이블 생성, seeding(초기 데이터 입력)

지난 시간에 app.module과 .env에 사용할 DB 서버의 위치를 지정해 주었으므로, DB를 생성, 사용해 보기로 https://ctrs.tistory.com/466 NestJS - TypeORM을 위한 app.module.ts 설정 기록 메모... @nestjs/typeorm, typeorm, mys

ctrs.tistory.com

 

사용할 명령어들

{
  "scripts": {
    "typeorm": "ts-node --require tsconfig-paths/register ./node_modules/typeorm/cli.js",
    "db:migrate": "npm run typeorm migration:run -- -d ./dataSource.ts",
    "db:migrate:revert": "npm run typeorm migration:revert -- -d ./dataSource.ts",
    "db:create-migration": "npm run typeorm migration:create -- ./src/migrations/",
    "db:generate-migration": "npm run typeorm migration:generate -- ./src/migrations -d ./dataSource.ts"
  },
}

 

 

1. 테스트를 위해 Mentions 엔티티에서 'category' 컬럼의 이름을 'type'으로 수정하였다.

 

별도의 수정 내역이 없었으니 DB에서는 여전히 category이다.

 

 

2. /scr 디렉토리 하단에 migrations 폴더 생성

 

 

사전에 설정 파일 dataSouce.ts에서 migration 내용을 읽어오는 경로를 지정한 곳이다.

dotenv.config();

const dataSource = new DataSource({
  migrations: [__dirname + '/src/migrations/*.ts'],
  });

export default dataSource;

 

 

3. migration 파일 생성 및 설정

$ npm run db:create-migration

> a-nest@0.0.1 db:create-migration
> npm run typeorm migration:create -- ./src/migrations/


> a-nest@0.0.1 typeorm
> ts-node --require tsconfig-paths/register ./node_modules/typeorm/cli.js migration:create ./src/migrations/

Migration C:\(중략)\a-nest\src/1699769430697-migrations.ts has been generated successfully.

 

/src 하단에 (숫자)-migraions.ts 파일이 생성되었다.

 

구분을 위해서 파일의 이름을 알아보기 쉽게 변경하고,

이 파일을 /src/migrations 폴더에 집어넣는다.

 

 

파일의 내용도 수정한다.

 

적용하고 싶은 내용을 up에,

실수한 경우 롤백을 위해서 적용하기 전으로 돌리는 내용을 down에 넣는다.

 

- before

import { MigrationInterface, QueryRunner } from "typeorm"

export class Migrations1699769430697 implements MigrationInterface {

    public async up(queryRunner: QueryRunner): Promise<void> {
    }

    public async down(queryRunner: QueryRunner): Promise<void> {
    }

}

 

- after

import { MigrationInterface, QueryRunner } from 'typeorm';

export class Migrations1699769430697 implements MigrationInterface {
  public async up(queryRunner: QueryRunner): Promise<void> {
    // up에는 수행할 내용이 들어간다
    // 예시
    await queryRunner.query(
      'ALTER TABLE `mentions` RENAME COLUMN `category` TO `type`',
    );
  }

  public async down(queryRunner: QueryRunner): Promise<void> {
    // down에는 수행하기 전, 혹은 수행된 내용을 롤백할 내용이 들어간다
    // 예시
    await queryRunner.query(
      'ALTER TABLE `mentions` RENAME COLUMN `type` TO `category`',
    );
  }
}

 

.query() 함수명에서 알 수 있듯이 안에는 쿼리문이 들어가야한다.

 

수작업으로 입력하지 않고

npm run db:generate-migration 명령어를 사용하는 방법도 있으나

불안정한 경우가 있으니 100% 의지하지 말고 조심하도록 하자

 

 

4. 변경 내용을 DB에 적용

$ npm run db:migrate

> a-nest@0.0.1 db:migrate
> npm run typeorm migration:run -- -d ./dataSource.ts


> a-nest@0.0.1 typeorm
> ts-node --require tsconfig-paths/register ./node_modules/typeorm/cli.js migration:run -d ./dataSource.ts

query: SELECT VERSION() AS `version`
query: SELECT * FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = '00_nestjs_typeorm' AND `TABLE_NAME` = 'migrations'
query: SELECT * FROM `00_nestjs_typeorm`.`migrations` `migrations` ORDER BY `id` DESC
0 migrations are already loaded in the database.
1 migrations were found in the source code.
1 migrations are new migrations must be executed.
query: START TRANSACTION
query: ALTER TABLE `mentions` RENAME COLUMN `category` TO `type`
query: INSERT INTO `00_nestjs_typeorm`.`migrations`(`timestamp`, `name`) VALUES (?, ?) -- PARAMETERS: [1699769430697,"Migrations1699769430697"]
Migration Migrations1699769430697 has been  executed successfully.
query: COMMIT

 

dataSource.ts에 설정된대로

/src/migrations 폴더 하단의 파일들을 찾아 변경 내용을 DB에 적용한다.

 

변경 내용이 적용된 DB에서도 컬럼명이 type으로 확인되었다.

 

 

그리고 이 내역은 DB 내 migrations 테이블에 저장된다.

 

나중에 다른 테이블에도 마이그레이션을 적용하기 위해 npm run db:migrate 명령어를 사용하더라도

migrations 테이블에 있는 내용은 제외되기 때문에

/src/migraions 폴더에서 'chageColumnNameFromCategoryToType.ts' 파일을 지워줄 필요는 없다.

 

 

5. 롤백

$ npm run db:migrate:revert

> a-nest@0.0.1 db:migrate:revert
> npm run typeorm migration:revert -- -d ./dataSource.ts


> a-nest@0.0.1 typeorm
> ts-node --require tsconfig-paths/register ./node_modules/typeorm/cli.js migration:revert -d ./dataSource.ts

query: SELECT VERSION() AS `version`
query: SELECT * FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = '00_nestjs_typeorm' AND `TABLE_NAME` = 'migrations'
query: SELECT * FROM `00_nestjs_typeorm`.`migrations` `migrations` ORDER BY `id` DESC
1 migrations are already loaded in the database.
Migrations1699769430697 is the last executed migration. It was executed on Sun Nov 12 2023 15:10:30 
GMT+0900 (대한민국 표준시).
Now reverting it...
query: START TRANSACTION
query: ALTER TABLE `mentions` RENAME COLUMN `type` TO `category`
query: DELETE FROM `00_nestjs_typeorm`.`migrations` WHERE `timestamp` = ? AND `name` = ? -- PARAMETERS: [1699769430697,"Migrations1699769430697"]
Migration Migrations1699769430697 has been  reverted successfully.
query: COMMIT

 

 

DB에서 롤백 확인

 

DB내 migrations 테이블에도 내용이 사라졌음을 확인

 

다음 db:migrate 명령 실행 시에는

다시 'chageColumnNameFromCategoryToType.ts'의 내용도 포함되어 마이그레이션 될 것이다.