Sequelize-cli와 PostgreSQL를 이용해서 데이터 Migration 및 Seed하기

Sungmin·2020년 4월 30일
1
post-thumbnail

이 글은 Getting Started with Sequelize and Postgres를 참고해서 작성하였습니다.


Sequelize가 뭐지?

  • Sequelize는 관계형 데이터베이스(MySQL, Postgres, MS SQL)을 위한 Node.js용 ORM입니다
  • Promise 기반입니다
  • ORM(Object Relational Mapping)은 SQL 대신에 데이터베이스와 소통할 수 있게 해주는 프로그래밍 언어입니다. 즉 SQL 대신에 코드로 쿼리문을 작성할 수 있게 해줍니다.

Sequelize-cli는 뭐지?

  • cli에서 알 수 있듯이 윈도우의 cmd나 Mac의 Terminal에서 Sequelize 관련 명령어를 쓸 수 있게 해주는 도구입니다.
  • 대표적으로 Model을 만들거나 Migration이나 Seed를 할 때 사용합니다.

Model은 뭐고 Migration은 뭐고 Seed는 뭐지?

  • Model은 Column 이름, 데이터 타입, Foreign Key 설정, 제약 조건 등 테이블의 스키마를 정의한 것입니다.
  • Migration은 Model에서 정의된 스키마를 바탕으로 실제 DB 서버에 테이블을 만들어주는 과정입니다.
  • Seed는 실제 데이터를 데이터베이스에 넣는 것을 과정입니다.

개발환경은 node.js를 사용하고, PostgreSQL을 사용합니다. npm 혹은 yarn, pgAdmin을 설치했다는 것을 가정합니다.

1. Dependency 설치

npm install sequelize sequelize-cli pg pg-hstore dotenv

혹은

yarn add sequelize sequelize-cli pg pg-hstore dotenv

을 입력해서 dependency들을 설치해주세요

  • sequelize는 sequelize 라이브러리 사용 및 PostgreSQL DB서버와 연결하게 해줌
  • sequelize-cli는 sequelize 관련 명령어로 데이터베이스 작업을 해주는 툴

2. .sequelizerc를 통해서 sequelize config 만들기

새로 .sequelizerc라는 파일을 만들고 다음과 같이 코드를 작성합니다.

const path = require('path')

module.exports = {
  'config': path.resolve('./database/config', 'config.js'),
  'models-path': path.resolve('./database/models'),
  'migrations-path': path.resolve('./database/migrations'),
  'seeders-path': path.resolve('./database/seeders')
}

'config': PostgreDB 서버와 연결할 connection string를 설정하는 폴더를 sequelize-cli가 생성하도록 해줌
'models-path': 테이블의 스키마를 정의해준 디렉토리. sequelize-cli가 이 파일을 바탕으로 마이그레이션 파일을 생성.
'migrations-path': 실제로 cli가 DB서버에 테이블을 만들도록 도와주는 디렉토리.
'seeders-path': 실제 데이터들을 넣는 폴더. cli가 데이터들을 보고 DB의 테이블에 데이터들을 넣음.


다음 명령어를 실행합니다.
npx sequelize init

./node_modules/.bin/sequelize 쓰는 대신에 npx가 ./node_modules/.bin을 가리키게 해줍니다.
./node_modules/.bin/sequelize 를 실행해야 하는 이유는 sequelize-cli가 global하게 설치 하지 않고 로컬에 설치했기 때문입니다. Global하게 설치하면 sequelize init으로 실행시킬 있습니다. Sequelize CLI를 사용하여 User API 만들기 참고

그러면 위의 사진 같이 `./database/` 디렉토리 안에 `config`, `models`, `migrations`, `seeders` 폴더가 생성됩니다.

database/config/안에 config.js를 밑의 코드로 대체해줍니다

require('dotenv').config()

module.exports = {
  development: {
    url: process.env.DEV_DATABASE_URL,
    dialect: 'postgres',
  },
  test: {
    url: process.env.TEST_DATABASE_URL,
    dialect: 'postgres',
  },
  production: {
    url: process.env.DATABASE_URL,
    dialect: 'postgres',
  },
}

3. DB서버에 데이터베이스 만들기

방법 1) pgAdmin에 들어가서 왼쪽에 Servers-PostgreSQL 12-Databases에 마우스 우클릭 하고 my_db라는 이름으로 Database를 만듭니다

방법 2) cli를 이용해서 Database를 만듭니다. Database를 만들기 위해 아래의 명령어를 입력합니다.

npx createdb my_db -U <db_user>

<db_user>는 Datases의 properties에서 볼 수 있습니다.


npm install dotenv 혹은 yarn add dotenv를 입력하여 dotenv를 설치하고 .dotenv 파일을 생성하여 아래와 같이 입력합니다.

DEV_DATABASE_URL=postgres://<db_user>:<db_password>@127.0.0.1:5432/my_db

방법2 에서 <db_user>가 어떤 것인지 확인해주세요

4. Model, Migration 만들기

테이블 시나리오

예를 들어 레딧 같은 커뮤니티 웹사이트를 만들어 본다고 가정해봅시다. 우리는 User, Post, Comment라는 테이블이 필요합니다. 그러면 다음과 같은 관계가 생깁니다.

  • User는 여러개의 Post를 가집니다. (One To Many)
  • User는 여러개의 Comment를 가집니다. (One To Many)
  • Post는 여러개의 Comment를 가집니다. (One To Many)

이러한 테이블 관계를 만들기 위해 계속해서 봅시다.


User, Post, Comment 모델 만들기

sequelize-cli로 User, Post, Comment 모델을 만들어 볼까요?

npx sequelize model:generate --name User --attributes name:string,email:string

npx sequelize model:generate --name Post --attributes title:string,content:text,userId:integer

npx sequelize model:generate --name Comment --attributes postId:integer,comment:text,userId:integer

위의 명령어들을 통해 /database/migration/database/model 디렉토리에 Migration과 Model을 생성해줍니다.

주의 : attirbute를 입력할 때 space 없이 입력합니다. ex) name:string,email:string

Foreign Key(userId, postId)에 NOT NULL이라는 제약조건을 넣습니다. 모델을 Eager loading 하기 위해서 입니다

userId: {
      type: Sequelize.INTEGER,
      allowNull: false,
    },

postId: {
      type: Sequelize.INTEGER,
      allowNull: false,
    },

/database/models/에 다음과 같은 코드를 추가합니다.

// database/models/user.js

module.exports = (sequelize, DataTypes) => {
  const User = sequelize.define('User', {
    name: DataTypes.STRING,
    email: DataTypes.STRING
  }, {});
  User.associate = function(models) {
    // associations can be defined here
    User.hasMany(models.Post, {
      foreignKey: 'userId',
      as: 'posts',
      onDelete: 'CASCADE',
    });

    User.hasMany(models.Comment, {
      foreignKey: 'userId',
      as: 'comments',
      onDelete: 'CASCADE',
    });
  };
  return User;
};
// database/models/post.js

module.exports = (sequelize, DataTypes) => {
  const Post = sequelize.define('Post', {
    title: DataTypes.STRING,
    content: DataTypes.TEXT,
    userId: DataTypes.INTEGER
  }, {});
  Post.associate = function(models) {
    // associations can be defined here
    Post.hasMany(models.Comment, {
      foreignKey: 'postId',
      as: 'comments',
      onDelete: 'CASCADE',
    });

    Post.belongsTo(models.User, {
      foreignKey: 'userId',
      as: 'author',
      onDelete: 'CASCADE',
    })
  };
  return Post;
};
// database/models/comment.js

module.exports = (sequelize, DataTypes) => {
  const Comment = sequelize.define('Comment', {
    postId: DataTypes.INTEGER,
    comment: DataTypes.TEXT,
    userId: DataTypes.INTEGER
  }, {});
  Comment.associate = function(models) {
    // associations can be defined here
    Comment.belongsTo(models.User, {
      foreignKey: 'userId',
      as: 'author'
    });
    Comment.belongsTo(models.Post, {
      foreignKey: 'postId',
      as: 'post'
    });
  };
  return Comment;
};
마이그레이션 하기

테이블의 스키마도 다 정의 했으니(모델링) DB에 테이블을 만들어 봅시다.
npx sequelize db:migrate
성공했다면 DB에 User, Post, Comment 테이블이 만들어졌을 겁니다.


5. 데이터 Seed 하기

sequelize-cli를 이용하여 seed 파일을 만들어 봅시다.

npx sequelize seed:generate --name User

npx sequelize seed:generate --name Post

npx sequelize seed:generate --name Comment

위의 명령어를 실행하면 /database/seeders/ 디렉토리 안에 YYYYMMDD-User.js, YYYYMMDD-Post.js, YYYYMMDD-Comment.js 가 만들어집니다.

실제 데이터를 테이블에 넣어 봅시다. 아래와 같이 작성하여 DB에 넣을 데이터를 만듭니다.

// database/seeds/YYYYMMDD-User.js

module.exports = {
  up: (queryInterface, Sequelize) => queryInterface.bulkInsert(
    'Users',
    [
      {
        name: 'Jane Doe',
        email: 'janedoe@example.com',
        createdAt: new Date(),
        updatedAt: new Date(),
      },
      {
        name: 'Jon Doe',
        email: 'jondoe@example.com',
        createdAt: new Date(),
        updatedAt: new Date(),
      },
    ],
    {},
  ),

  down: (queryInterface, Sequelize) => queryInterface.bulkDelete('Users', null, {}),
};
// database/seeds/YYYYMMDD-Post.js

module.exports = {
  up: (queryInterface, Sequelize) =>
    queryInterface.bulkInsert(
      "Posts",
      [
        {
          userId: 1,
          title: "hispotan de nu",
          content:
            "Nulla mollis molestie lorem. Quisque ut erat. Curabitur gravida nisi at nibh.",
          createdAt: new Date(),
          updatedAt: new Date()
        },
        { 
          userId: 2,
          title: 'some dummy title',
          content:
            "Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque. Quisque porta volutpat erat.",
          createdAt: new Date(),
          updatedAt: new Date()
        }
      ],

      {}
    ),

  down: (queryInterface, Sequelize) =>
    queryInterface.bulkDelete("Posts", null, {})
};
// database/seeds/YYYYMMDD-Comment.js

module.exports = {
  up: (queryInterface, Sequelize) =>
    queryInterface.bulkInsert(
      "Comments",
      [
        {
          userId: 1,
          postId: 2,
          comment:
            "Nulla mollis molestie lorem. Quisque ut erat. Curabitur gravida nisi at nibh.",
          createdAt: new Date(),
          updatedAt: new Date()
        },
        {
          userId: 2,
          postId: 1,
          comment:
            "Maecenas tincidunt lacus at velit. Vivamus vel nulla eget eros elementum pellentesque. Quisque porta volutpat erat.",
          createdAt: new Date(),
          updatedAt: new Date()
        }
      ],
      {}
    ),

  down: (queryInterface, Sequelize) =>
    queryInterface.bulkDelete("Comments", null, {})
};

sequelize-cli를 이용하여 데이터를 DB에 Seed 해봅시다
npx sequleize db:seed:all

성공했으면 데이터가 실제 테이블에 들어간 것입니다. 여기까지 Sequelize와 Sequelize-cli를 이용하여 Model, Migration 그리고 Seed까지 해봤습니다. 끝!

profile
Share everything that I like

0개의 댓글