본문 바로가기

Back-End

[Node.js ORM] Sequelize-cli 사용 방법 정리

Sequelize (ORM 도구)

 

Sequelize

 

sequelize.org

데이터베이스를 관리하기 위한 도구 중 Node.js 기반 ORM 버전이네요.

sequelize-cli 는 이 기능을 명령창(터미널)에서 실행하기 위한 개발 버전

터미널에서 sequelize-cli -h 실행으로 sequelize의 다양한 명령어를 확인하세요.

여튼, 여기서는 실제 작업에 필요한 기능들을 누적 정리합니다.

 

Sequelize 초기 셋팅

> sequelize-cli init

실행하면 아래 sequelize에 필요한 폴더를 생성합니다.

  • config, 데이터베이스에 연결 설정을 CLI에 알려주는 구성 파일 포함
  • models, 프로젝트의 모든 모델을 포함
  • migrations, 모든 마이그레이션 파일 포함
  • seeders, 모든 시드 파일 포함 (임시 데이터 삽입을 위한 도구)

 

Model 만들기

DB에 테이블을 생성하기 위한 하나의 과정으로 아래 명령 실행

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

*설명: User 라는 테이블명으로 필드는 firstName, LastName, email 로 구성된 설정 파일 생성

실행하면 아래 폴더와 파일이 생성되며 migration 파일에는 Sequelize가 알아서 자동으로 묻지도 따지지도 않고
Primary id 필드와 날짜 필드를 삽입해 줍니다. (불필요할 경우 옵션에서 비활성 가능)

/models/User.js
/migrations/20200831190449-create-user.js

위 예는 필드가 몇개 안될 경우이고 실제 필드가 다수일 땐 저기에 다 나열하는 것은 귀찮은 일입니다.
방법은 터미널에선 최소 필드로 생성하고 생성된 위 두개의 파일을 열어 실제 필드를 추가 작성하면 됩니다.

 

Table 생성

필요한 필드를 추가했으면 아래 db:migrate 명령어로 해당 DB에 TABLE을 생성합니다.

> sequelize-cli db:migrate

DB에 마지막 생성된 테이블을 drop 하거나 전체 테이블을 drop 시킬 수 있습니다.

(?) 이미 존재하는 테이블에 migration 파일을 이용에 필드를 추가하는 방법을 찾는 중인데... 혹시 아시는 분 정보 공유 부탁합니다.

> sequelize-cli db:migrate:undo

> sequelize-cli db:migrate:undo:all



생성된 테이블에 seed(임시데이터) 넣기

씨앗이 되는 임시데이터를 넣기 위한 seed 파일 생성

> sequelize-cli seed:generate --name user

위 명령으로 seeders/ 폴더 밑에 생성된 xxxxxxxxxxxxxx-user.js 파일을 편집기에서 열고 필드 추가 작성

  up: (queryInterface, Sequelize) => {
    return queryInterface.bulkInsert('Users', [{
      firstName: 'John',
      lastName: 'Doe',
      email: 'example@example.com',
      phone: '010-4444-3333',  //<-- 필드 추가
      sex: 'male',  //<-- 필드 추가
      createdAt: new Date(),
      updatedAt: new Date()
    }]);
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.bulkDelete('Users', null, {});
  }

필드 작성 후 seed:all로 DB 테이블에 작성한 데이터 넣기 (INSERT)

> sequelize-cli db:seed:all

DB를 확인해 보면 데이터가 insert 되어 있습니다.
역시 seed에도 undo가 제공됩니다.

> sequelize-cli db:seed:undo



외래키(ForeignKey) 설정하기

Sequelize에서 종속 테이블간의 ForeignKey(이하 FK)를 설정하는 방법입니다.

DB의 SQL 동작인 CRUD(Create, Read, Update, Delete)를 NodeJS로 쉽게 관리하는 도구인데
FK 생성과 연결은.... 적잖이 난감했습니다. (아직 Node와 Sequelize 환경에 적응 중)
model:generate 로 생성된 model과 migration 파일들을 열어 관련 코드를 작성해야 하더군요.

참고로 예시의 users 테이블과 cards 테이블은 1:n의 관계입니다. (한 사람은 여러개의 카드를 갖는다)

처음엔 migration 파일에 아래처럼 키가 되는 필드와 하위 옵션 references 를 작성하고 db:migrate 실행하니
실제 테이블에 FK 연결이 생성되었습니다. (ㅇㅇ? 그럼 됐네?)

/migrations/202008041102333-create-cards.js

"use strict";
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable(
      "Card",
      {
        userName: {
          allowNull: false,
          type: Sequelize.STRING,
        },
        //------ 추가 필드,옵션 시작 ----
        userId: {
          allowNull: false,
          type: Sequelize.INTEGER,
          onDelete: "CASCADE",
          references: {
            model: "Users",
            key: "id",
          },
        },
        //------ 추가 필드,옵션 끝 ----
      },
      {
        charset: "utf8",
        collate: "utf8_general_ci",
      }
    );
  },
  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable("Cards");
  },
};


네.. FK로 연결된 테이블을 쓰기엔 아무 문제가 없습니다.
B.U.T, 이젠 Node 환경에서 JS로 컨트롤 할 것이기에 Sequelize에게 테이블의 관계를 알려줘야 합니다.

아래 3개의 파일을 열어 추가해 줍니다.

/migrations/202008041102333-create-cards.js  <--- 위 코드 예시에 이미 작성

/models/users.js
/models/cards.js

/*----------------------
/models/users.js 코드
-----------------------*/
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
  class User extends Model {
    static associate(models) {
      // define association here
      User.hasMany(models.Invitation, {
        foreignKey: "userId",
      });
    }
  }
  User.init(
    {
      firstName: DataTypes.STRING,
      lastName: DataTypes.STRING,
      email: DataTypes.STRING,
      password: DataTypes.STRING,
    },
    {
      sequelize,
      modelName: "User",
    }
  );
  return User;
};



/*----------------------
/models/cards.js 코드
-----------------------*/
"use strict";
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
  class Card extends Model {
    static associate(models) {
      // define association here
      Card.belongsTo(models.User, {
        foreignKey: { name: "userId", allowNull: false },
        onDelete: "CASCADE",
      });
      // Card 하위로 연결할 FK가 있을 경우
      // Card.hasMany(models.Photo, {
      //  foreignKey: "cardId",
      // });
    }
  }
  Card.init(
    {
      nameMale: DataTypes.STRING,
      phoneMale: DataTypes.STRING,
      photo: DataTypes.STRING,
    },
    {
      sequelize,
      modelName: "Card",
    }
  );
  return Card;
};


작성시 아래와 같은 형식입니다. (onDelete CASCADE 는 부모가 삭제되면? 자식들도 뒤를 따르나이다)

users 테이블:  1 = hasMany(models.Card. { ... });
cards 테이블:  n = belongsTo(models.User, { ... , onDelete: "cascade"});

이 외에 1:1, n:m 등의 관계를 지원하는 Association 메소드가 있으니..

너무너무 보기 쉽고 이해가 편하고 배려가 가득한 최고의 가독성! (거짓말은 요란하다)

Associations 공식 문서를 참고해보세요.

 

짧은 소고:
Sequelize의 작업 효율성까지는 잘 모르겠지만 SQL 구문을 직접 작성하고 DB 관리툴을 쓴다면
ORM이란 작업 과정이 추가되는 것 이상의 의미가 있을까 싶은 건 나만의 생각이겠지...?

 

--- 여기까지 누적 ---

내용 중 잘못된 부분이나 누락된 부분은 댓글 부탁합니다.

'Back-End' 카테고리의 다른 글

CORS - 크로스 도메인 소스 공유 패키지  (0) 2020.09.21