2019. 08. 11 수정

seed는 서버가 시작될 때 애플리케이션이 가지고 있어야 할 정적인 데이터들을 DB에 추가해주는 기능을 의미합니다.

단어 그대로 씨앗을 뿌리는 것이죠.

이번 글에서는 sequelize 기능인 seeder에 대해 알아보도록 하겠습니다.




1. 준비 작업

express-generator, sequelize-cli로 프로젝트 스켈레톤을 구성합니다.


이어서 아래의 명령어를 실행하여, user 모델을 정의하도록 하겠습니다.

# sequelize model:create --name user --attributes "email:string, name:string, password:string"

추가적인 컬럼 옵션은 부여하지 않도록 하겠습니다.

따라서 migration 파일을 수정할 필요도 없겠네요.


이제 준비 작업을 마쳤으므로 본격적으로 seed를 추가해보도록 하겠습니다.





2. seed 파일 작성

sequelize-cli를 실행했다면 seeders 폴더가 있는데, 현재 seeders 폴더에는 아무 파일도 존재하지 않습니다.


sequelize-cli를 통해 seed 파일을 생성해보겠습니다.

# sequelize seed:generate --name test


그러면 seeders 폴더에는 타임스탬프-test.js 이름의 파일이 생성될 것입니다.

'use strict';

module.exports = {
up: (queryInterface, Sequelize) => {
...
},

down: (queryInterface, Sequelize) => {
...
}
};


이 파일을 열어보면 migration 파일과 똑같은 구조임을 확인할 수 있습니다.

  • up 프로퍼티
    • seed를 생성할 때 수행할 로직
  • down 프로퍼티
    • seed를 되돌릴 때 수행할 로직


주석으로 예제가 제시되어 있으므로 이를 참고하여, 일단은 up 프로퍼티만 작성하도록 하겠습니다.

/seeders/타임스탬프-test.js

'use strict';

module.exports = {
up: (queryInterface, Sequelize) => {

let datas = [];
for(let i = 0; i < 10; i++){
let obj = {
email: "test" + i + "@example.com",
name: "testUser" + i,
password: "1234",
createdAt: new Date().toISOString().replace(/T/, ' ').replace(/\..+/, ''),
updatedAt: new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '')
}
datas.push(obj)
}

return queryInterface.bulkInsert('users', datas, {});
},

down: (queryInterface, Sequelize) => {

}
};
  • bulkInsert() 메서드
    • 데이터를 추가하는 메서드입니다.
      • 첫 번째 인자는 "user"가 아니라 "users"입니다.
      • 즉, 객체 이름이 아닌 테이블의 이름을 인자로 전달해야 합니다.
        • 참고) /models/user.js 파일

      • 두 번째 인자에 추가할 데이터를 배열로 전달합니다.
        • 배열의 요소는 객체로 정의되어 있는데, 각 객체의 속성은 테이블의 컬럼명이고, 값은 실제 데이터로 정의합니다.
        • 예를 들어, 위의 예에서 obj 객체에는 email, name, password, createdAt, updatedAt이 속성으로 정의되어 있고, 이는 곧 테이블의 칼럼 명입니다.
          • 참고로 sequelize-cli로 모델을 생성하면, 자동으로 테이블의 id, createdAt, updatedAt 컬럼이 생성됩니다.
          • id 값은 자동으로 증가하지만, createdAt 과 updatedAt 컬럼은 예제처럼 직접 값을 할당해야 해줘야 합니다.



seed된 결과 화면을 보시면 위와 같습니다.

sequelize-cli가 추가한 createdAt과 updatedAt 컬럼은 날짜 format이 timestamp 이므로, 값을 할당할 때도 format을 맞춰야 seed 할 수 있습니다.

format이 맞지 않으면 에러가 발생합니다.


따라서 예제에서 ISO8601 포맷을 offset이 없는 timestamp로 바꿔줬습니다. ( 참고 )

물론 국제화가 필요하다면 createdAt, updateAt 컬럼 타입을 바꿔줘도 됩니다.

createdAt: new Date().toISOString().replace(/T/, ' ').replace(/\..+/, ''),
updatedAt: new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '')



이제 seed 파일을 작성했으니 실제로 DB에 반영하는 작업을 해야 합니다.


준비 작업에서 migration 파일만 생성했고, migrate를 하지 않았으므로 커맨더 창에서 migrate 명령어를 실행합니다.

# sequelize db:migrate

일부러 migrate를 지금 하는 이유는 seed를 하기 전에 migrate를 먼저 실행해야 한다는 것을 말씀드리기 위함입니다.

테이블의 필드가 정의되어 있어야 seed를 할 수 있기 때문이죠.


이어서 아래의 명령어를 실행하면, seeder 폴더에 있는 모든 파일들의 up 프로퍼티에 있는 함수의 로직을 수행합니다.

# sequelize db:seed:all


정말로 데이터가 추가 되었는지 MySQL에서 확인해보세요!





3. seed 되돌리기

seed된 것을 되돌리는 방법도 있는데, 되돌리는 방법은 더 간단합니다.


우선 seed 파일에서 down 프로퍼티에 아래와 같이 함수를 작성합니다. 

/seeders/타임스탬프-test.js

down: (queryInterface, Sequelize) => {
return queryInterface.bulkDelete('users', null, {});
}

seed를 되돌리려면, bulkDelete() 메서드를 호출합니다.

그리고 어떤 테이블의 seed를 되돌릴 것인지 명시하기 위해, 첫 번째 인자로 "users"를 전달합니다.


seed했던 데이터를 되돌리는 명령어는 아래와 같습니다.

# sequelize db:seed:undo:all


정말로 seed된 데이터가 되돌아갔는지 MySQL에서 확인해보세요.





이상으로 sequelize에서 seed 하는 방법을 알아보았습니다.


seed는 동적으로 처리되는 DB작업이 아닌, 정적인 데이터들을 서버를 실행하면서 생성할 필요가 있을 때 사용하면 좋습니다.

예를 들면, 수강신청 웹 서비스를 구현한다고 했을 때, 강의 목록은 정적인 데이터입니다.

따라서 서버를 시작할 때 seed를 이용하여 강의 목록을 DB에 저장하는 용도로 활용할 수 있습니다.