[Back-end] Sequelize로 migration 하기

조성철 (JoSworkS)·2020년 4월 28일
3
post-thumbnail

WDMA 프로젝트는 그 동안 익힌 기술들을 다시 한 번 복습한다는 생각으로 시작한 프로젝트이다. 그래서 Stroll 프로젝트에서 사용하였던 ORM인 Sequelize를 다시 한 번 사용해 봄으로써 Sequelize의 장/단점을 확인해 보고 싶었다.

Sequelize에 대한 설명은 아래 링크를 참고하길 바란다.
참고: https://velog.io/@josworks27/Sequelize-Association

DB Schema

  • Table: images, dresses, stores, chats, users, events, customers
  • Association: 1:n, 1:1

Migration

Sequelize는 TypeORM과 마찬가지로 CLI를 지원하고 있다. 그래서 터미널에서 명령어를 통해 테이블에 해당하는 모델의 구조를 만드는게 가능하고, 구체적인 모델의 설정이 끝나면 MySQL에 Migration하는 작업도 명령어로 가능하다.

그러면 Migration까지 어떤 과정을 거치는지 알아보도록 하겠다.

1. 초기 설정

먼저, ORM의 초기설정은 아래의 명령어를 통해 간단히 할 수 있다.

$ npx sequelize-cli init

명령어를 실행하고 나면, 실행한 root에 아래와 같은 폴더들이 만들어 진다.

  • config: contains config file, which tells CLI how to connect with database
  • models: contains all models for your project
  • migrations: contains all migration files
  • seeders: contains all seed files

2. config.js 설정

./config/config.json 파일이 기본적으로 생성이 되는데, 환경변수를 이용하기 위해서는 config.js로 바꾸는 작업이 필요하다.

// config.js

require('dotenv').config();

const env = process.env;

module.exports = {
  development: {
    username: env.MYSQL_USERNAME,
    password: env.MYSQL_PASSWORD,
    database: env.MYSQL_DATABASE,
    host: env.MYSQL_HOST,
    dialect: 'mysql',
    operatorsAliases: false,
  },
};

3. Model 생성

Model을 만드는 것도 아래의 예시 명령어와 같이 CLI로 가능하다.

$ npx sequelize-cli model:generate --name User --attributes firstName:string,lastName:string,email:string

위 명령어를 실행하면 ./models와 ./migrations에 명령어로 작성한 그대로 Model이 생성이 된다. migrations은 MySQL에 실제 이식될 테이블의 형태를 결정하며, models는 ORM을 통해 개발환경에서 MySQL를 다루기 위한 것이라고 생각하면 좋을 듯 하다.

그렇기 때문에, migrations의 속성과 models의 속성은 동일해야 한다.

아래는 실제 작업물의 customers 테이블에 대한 코드이다. 기본적으로 필요한 PK인 id와 createdAt, updatedAt을 제외한 속성이 동일한 것을 알 수 있다.

createdAt, updatedAt은 기본값으로 들어가도록 되어 있으며 설정 가능하다.

// ./migrations/20200423100019-create-customers.js

'use strict';
module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('customers', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER,
      },
      name: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      age: {
        type: Sequelize.INTEGER,
        allowNull: false,
      },
      gender: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE,
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE,
      },
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('customers');
  },
};
// ./models/customers.js

'use strict';
module.exports = (sequelize, DataTypes) => {
  const customers = sequelize.define(
    'customers',
    {
      name: {
        type: DataTypes.STRING,
        allowNull: false,
      },
      age: {
        type: DataTypes.INTEGER,
        allowNull: false,
      },
      gender: {
        type: DataTypes.STRING,
        allowNull: false,
      },
    },
    {}
  );
  customers.associate = function (models) {
    // associations can be defined here
    models.customers.hasMany(models.events);
  };
  return customers;
};

4. migration 실행

모델에 대한 설정이 끝나면 아래 명령어로 MySQL으로 이식이 가능하다.

$ npx sequelize-cli db:migrate

모든 이식을 되돌리고 싶을 때는 아래의 명령어를 참고하면 된다.

$ npx sequelize-cli db:migrate:undo:all

주의 사항

주의해야 할 점으로 환경변수 모듈을 사용하기 위해 config.json을 config.js로 변경하였는데, 확장자가 js로 변경됨으로써 생성된 model들을 처리를 담당하는 ./models/index.js가 config.js의 설정을 읽지 못하게 되는 문제가 발생한다.

따라서 아래와 같이 코드를 다듬어 줄 필요가 있다.

// ./models/index.js

// 변경 전
const config = require(__dirname + '/../config/config.json')[env];

// 변경 후
const config = require(`${__dirname}/../config/config.js`)[env];

참고 자료

0개의 댓글