// 에드센스

nodejs로 개발을 하던 중 데이터베이스 테이블에 컬럼을 추가할 일이 있었다.

그때 사용한 방법을 기록해볼까 한다.


1. 데이터베이스 마이그레이션?

 

 

어디서 많이 들어보긴했지만 정확한 의미는 잘 몰랐다.

우선 마이그레이션이란 큰 의미로

"한 운영환경으로부터 다른 운영환경으로 옮기는 작업"

 

이라고 할 수 있다. Migration을 사전에 검색하면 나오는 '이주, 이송'의 개념이다.

하드웨어, 소프트웨어, 네트워크 등 넓은 범위에서 마이그레이션의 개념이 사용되고 있다. 

 

 

데이터베이스에서 한 예시로,

개발환경에서 스키마와 운영환경에서 스키마에 차이가 있을때 마이그레이션을 진행한다고 할 수 있다.

작게는 테이블 생성과 수정부터 하나의 애플리케이션 혹은 전체 시스템을 옮기는 것까지를 마이그레이션이라고 한다.

나는 데이터베이스에서 한 테이블에 컬럼을 추가하고자 한다.

 

 

 

 


2. 실습

현재 Nodejs에서 Sequelize 라이브러리로 데이터베이스를 조작하고 있다.

개발단계에서는 sync({force: true})를 통해서 컬럼을 강제로 추가할 순 있겠지만 운영단계에서는 불가능하다.

따라서 Sequelize에서 지원하는 마이그레이션으로 컬럼을 추가해볼까 한다.

 

 

0. Sequelize CLI 설치

# using npm
npm install --save-dev sequelize-cli
# using yarn
yarn add sequelize-cli --dev

 

 

 

1. init 명령

# using npm
npx sequelize-cli init
# using yarn
yarn sequelize-cli init

init 명령을 실행하면

  • config, 데이터베이스에 연결하는 방법을 CLI에 알려주는 구성 파일이 포함돼 있다.
  • models, 프로젝트의 모든 모델을 포함한다.
  • migrations, 모든 마이그레이션 파일 포함한다.
  • seeders, 모든 시드 파일을 포함한다.

이 4개의 폴더가 생성된다.

 

 

 

2. 데이터베이스 설정

config/config.json 파일에서 각 환경별로 나의 데이터베이스 정보를 입력해두어야 한다.

{
  "development": {
    "username": "mydb",
    "password": "mydb-password",
    "database": "postgres",
    "host": "mydb-dev.1234.ap-northeast-2.rds.amazonaws.com",
    "post": 5432,
    "dialect": "postgres"
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mysql"
  }
}

개발환경만 설정했다.

Sequelize CLI는 기본값이 mysql로 설정돼있다. 다른 데이터베이스를 사용하는 경우 "dialect"옵션의 내용을 수정해줘야한다.

또 Sequelize는 각 데이터베이스에 대한 포트로 기본값들을 사용한다.(postgres의 경우 5432포트)

다른 포트를 지정해야 하는 경우 "port"필드를 추가하여 설정할 수 있다.

 

 

 

3. 마이그레이션 파일 생성

sequelize migration:create --name test-migration

이 명령어로 마이그레이션 설정 파일을 생성한다. --name 옵션으로 파일의 이름을 지정한다.

그러면 migration 폴더에 20220318184913-test-migration.js 이라는 파일이 생성될 것이다.(날짜-이름.js)

 

 

이렇게 생긴 파일이다.

"use strict"

module.exports = {
  up: function (queryInterface, Sequelize) {
    /*
      Add altering commands here.
      Return a promise to correctly handle asynchronicity.

      Example:
      return queryInterface.createTable('users', { id: Sequelize.INTEGER });
    */
  },

  down: function (queryInterface, Sequelize) {
    /*
      Add reverting commands here.
      Return a promise to correctly handle asynchronicity.

      Example:
      return queryInterface.dropTable('users');
    */
  },
}

up 메소드에는 마이그레이션 할 내용을 기재하고 

down 메소드에는 롤백할 내용을 기재한다.

 

 

컬럼을 추가하는 up메서드를 작성해보자.

'use strict';

module.exports = {
  up: async (queryInterface, Sequelize) => {
    return queryInterface.addColumn('product', 'url', {
      type: Sequelize.STRING,
      allowNull: false,
      defaultValue: 'https://myProduct.s3.ap-northeast-2.amazonaws.com/default.png',
    });
  },

  down: async (queryInterface, Sequelize) => {
    return queryInterface.removeColumn("product", "url")
  },
};

up 메소드에는 product테이블에 상품의 사진을 저장하는 url 컬럼을 추가한다.

down 메소드에는 up 메소드에 대한 롤백 내용을 기재해보았다.

 

 

 

4. 마이그레이션 진행

sequelize db:migrate --env development

를 통해서 up 메소드에 기재한 마이그레이션을 실행할 수 있다.

--env는 default로 development로 설정돼있긴하다.

 

 

 

5. 롤백

롤백은 이렇게 해주면 된다.

sequelize db:migrate:undo --env development

 

 

 

6. 다중 마이그레이션 

해보진 않았지만 잘 정리된 블로그의 내용을 참고했다.

 

만약 컬럼을 여러개 추가할 때는 어떻게 해야할까.

up() 함수는 프라미스를 리턴하게 되어있는데 promise로 구성된 배열을 반환해도 된다.

컬럼을 여러개 추가할 것이라면 addColumn()을 배열에 담아 리턴하면 된다.

물론 롤백할 때도 동일하게 removeColumn()를 배열에 담아서 반환한다. 

module.exports = {
  up: function (queryInterface, Sequelize) {
    return [
      queryInterface.addColumn("product", "url", {
        type: Sequelize.STRING,
      }),
      queryInterface.addColumn("product", "price", {
        type: Sequelize.STRING,
      }),
    ]
  },

  down: function (queryInterface, Sequelize) {
    return [
      queryInterface.removeColumn("product", "url"),
      queryInterface.removeColumn("product", "price"),
    ]
  },
}

물론 직접 raw 쿼리를 사용할 수도 있다.

module.exports = {
  up: function (queryInterface, Sequelize) {
    var sql = "ALTER TABLE product ADD COLUMN url varchar(255) NOT NULL"

    return queryInterface.sequelize.query(sql, {
      type: Sequelize.QueryTypes.RAW,
    })
  },

  down: function (queryInterface, Sequelize) {
    var sql = "ALTER TABLE product DROP COLUMN url"

    return queryInterface.sequelize.query(sql, {
      type: Sequelize.QueryTypes.RAW,
    })
  },
}

 

 

 

 

 

 

 

참고:

더보기

+ Recent posts