나의 발자취

[Node.js] sequelize-CLI로 테이블(모델) 생성, 테이블 구조 변경 migration, seed 데이터 추가 본문

Backend

[Node.js] sequelize-CLI로 테이블(모델) 생성, 테이블 구조 변경 migration, seed 데이터 추가

달모드 2024. 10. 16. 16:31

시퀄라이저 CLI로 테이블을 생성해주기 위해, 터미널에 아래 명령을 입력한다.

1. User 모델 생성

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

모델을 생성할거고, 이름은 User, 모델 안에 이름을 String으로 하고, 이메일도 String으로 하는 속성을 생성해라. 라는 뜻이다.

 

주의! attributes 속성값들 사이 콤마 뒤에 스페이스바를 띄우면 안된다.

-올바른 예: --attributes name:string,email:string (O)

-틀린 예: --attributes name:string,(띄고)email:string (X)

 

만약에 틀리게 명령어를 입력하면, 아래와 같이 오류가 나온다.

 

올바른 예

 

2. Task 모델 생성

npx sequelize-cli model:generate --name Task --attributes title:string,userId:integer

 

이렇게 하면, migrations, models 폴더 아래와 같이 내가 위에서 정의한 대로 모델이 생성되면서 해당하는 파일들이 생성된 것이 확인된다! 이대로 post.db 안에도 테이블이 생겼을 것이다.

 

참고로, (중요) 이렇게 생성된 migrations 파일 앞의 숫자는 타임스탬프이다. 생성된 시간 순서대로 실행되기 때문에, 테이블을 생성할 때의 순서도 중요하다.

 

2. DB 구조 변경 (db:migrate)

db:migrate 을 사용하면 데이터베이스에 대한 마이그레이션이 수행된다. 이 과정에서 발생하는 주요 변화는 다음과 같다:

1. 데이터베이스 구조 변경

  • 테이블 생성: 마이그레이션 파일에 정의된 내용을 바탕으로 새로운 테이블이 생성된다. 예를 들어, 모델 정의에 따라 Post 또는 Comment 테이블이 데이터베이스에 추가될 수 있다.
  • 컬럼 추가/수정/삭제: 기존 테이블에 새로운 컬럼을 추가하거나, 컬럼의 속성을 변경하거나, 불필요한 컬럼을 삭제하는 작업이 이루어진다.

2. 마이그레이션 기록

  • 마이그레이션 로그: Sequelize는 마이그레이션이 성공적으로 완료되면, SequelizeMeta라는 특별한 테이블에 해당 마이그레이션의 기록을 추가한다. 이를 통해 어떤 마이그레이션이 이미 적용되었는지를 추적할 수 있다.

3. 데이터베이스 동기화

  • 스키마 동기화: 마이그레이션을 통해 데이터베이스 스키마가 모델 정의와 동기화된다. 이는 애플리케이션의 코드와 데이터베이스 간의 일관성을 유지하는 데 중요한 역할을 한다.

 

20241016060843-create-task.js

에서, userId 필드에다가 외래키 참조를 위한 조건을 조금 더 추가해준다.

(+ 아래에서 에러 트러블슈팅을 하면서 발견한 사실인데, model: 뒤에 오는 값으로는 모델 이름 "User"가 아닌 테이블명인 "Users"를 지정해주어야 한다. 아래 코드 스니펫에는 정상적으로 돌아가는 값으로 수정해놓았다.)

      userId: {
        type: Sequelize.INTEGER,
        allowNull: false,
        references: {
          model: "Users",
          key: "id",
        },
        onDelete: "CASCADE",
        onUpdate: "CASCADE",
      },

 

 

  • ON DELETE CASCADE: 부모 레코드 삭제 시 자식 레코드도 자동 삭제.
  • ON UPDATE CASCADE: 부모 레코드 업데이트 시 자식 레코드도 자동 업데이트.

references: {} 안의 항목들은 User 모델의 id 필드를 기본키(PK)로 참조할 것이라는 뜻이다. 현재 Task 테이블의 userId 필드에 대한 구조를 짜고 있으므로, userId 필드는 외래키(FK)가 될 것이다. 즉, 이렇게 구조를 짜고 나면

 

Users 테이블의 id 필드에는 주황색 키(PK)가,

Tasks 테이블의 id 필드에는 회색 키(FK) 아이콘이 나타날 것이다!

 

 

확인을 위해, 터미널
npx sequelize-cli db:migrate
를 입력해준다.
(migrate를 취소하는 방법은 npx sequelize-cli db:migrate:undo:all 를 사용한다. 체크포인트별로 undo할수도 있음. 이건 챗 지피티에게~)

 

그러면 위에서 말했던 대로, 열쇠 아이콘이 생긴 것을 볼 수 있다!

Users 테이블의 id 필드에는 주황색 키(PK)가,
Tasks 테이블의 id 필드에는 회색 키(FK) 아이콘이 나타날 것이다!

 

 

 

3. DB 시드 파일 생성 (seed:generate)

시드(seed) 파일은 데이터베이스에 초기 데이터를 삽입하는 데 사용된다. 아래의 명령어를 순차적으로 입력한다.

npx sequelize-cli seed:generate --name demo-user

npx sequelize-cli seed:generate --name demo-task

 

그리고, 20241016062945-demo-user.js 로 가서 async up()안의 주석의 마지막 부분부터 엔터를 쳐서 아래와 같은 코드를 추가해준다.

 

샘플 데이터로 두 개만 넣어줄거고, bulkInsert()의 첫번째 인자는 테이블 명이다.

 

마찬가지로 20241016062953-demo-task.js 에도 seed data 추가

 

 

 

그리고 터미널 창에 가서 

npx sequelize-cli db:seed:all 를 입력한다.

(+ 여기서부터 위에서 말한 트러블슈팅)

 

위와 같이 터미널에 에러가 뜬다. 뭔가 잘못된것...터미널에 쳐서

sqlite3 post.db 에 들어간다.

sqlite> .schema Tasks 를 입력해본다. 로그를 보면, 'Users'가 되어야하는데 'User'인 것이 보인다.

(원인 파악 완)

 

migrations > 20241016060843-create-task.js에 보면, model: "Users"여야 하는데 에 "User"로 선언을 했었다.

그래서 이 값을 고치고,

sqlite> drop table Tasks;를 해준다.

sqlite> delete from SequelizeMeta; 도 해준다. 그리고 .quit 을 쳐서 나온다.

 

다시 npx sequelize-cli db:migrate

 

이러고 다시

sqlite3 post.db 에 들어간다.

sqlite> .schema Tasks 를 입력해본다.

그러면 위와 같이 Tasks의 테이블이 'Users' 테이블을 참조하고 있다는 것이 확인된다.

 

 

이제 다시 npx sequelize-cli db:seed:all 를 입력한다.

성공적으로 시드 데이터가 들어갔다!

 

 

4. 기존 테이블에 컬럼 추가하는 작업

이제 Tasks 테이블에 description 컬럼을 추가해줄 것이다.

npx sequelize-cli migration:generate --name add_column-task

하면 아래와 같은 파일이 생성된다.

 

기본 틀은 아래와 같이 생겼는데, up()은 쿼리가 성공하면 실행되고, down()은 쿼리가 실패하면 실행되는 메서드이다.

'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
  async up (queryInterface, Sequelize) {
    /**
     * Add altering commands here.
     *
     * Example:
     * await queryInterface.createTable('users', { id: Sequelize.INTEGER });
     */
  },

  async down (queryInterface, Sequelize) {
    /**
     * Add reverting commands here.
     *
     * Example:
     * await queryInterface.dropTable('users');
     */
  }
};

 

 

up() 안에 아래와 같이 작성을 해준다.

async up (queryInterface, Sequelize) {
    await queryInterface.addColumn("Tasks", "description", {
      type: Sequelize.STRING,
      allowNull: true,
    })
  },

 

이것은 alter table Tasks add column description varchar(10)과 똑같다.

 

터미널에 가서 db 마이그레이트 명령을 해준 후, post.db에 확인을 해준다.

 

그러면 아래와 같이 description 컬럼이 생성된 것이 확인된다!

 

 

models > task.js 에 description용 데이터가 따로 없기 때문에, 따로

description: DataTypes.STRING

 

라는 라인을 추가를 해준다.

전 / 후

 

 

Comments