본문으로 바로가기

sequelize ORM를 이용한 MySQL 활용

category DB, ORM/🧊 MySQL 2020. 3. 12. 18:46

ORM는 우리가 사용하는 프로그래밍 언어를 SQL문으로 변환해준다. python의 경우 장고 ORM, node.js 에는 type ORM, 시퀄라이즈(sequelize) 등이 존재한다. SQL문을 작성하지 않고 평소 하던 JS나 python으로 DB를 제어할 수 있어서 편하다. 그러나 ORM에 너무 의존하는 것은 좋지 않다. ORM에 문제가 생기거나 속도가 중요해질때는 SQL을 활용해야 한다. 결론은 ORM과 SQL 둘 다 배워야 한다는 것이다.

 

sequelize 설치

npm i sequelize
npm i -g sequelize-cli // sequelize를 터미널에서 사용하게 해줌
npm i mysql2 // mysql 사용을 위해 설치

 

sequelize 실행하기

sequelize init

config/config.json, models/index.js, migrations, seeders 폴더, 파일이 생성된다.

여기서 가장 중요하고 알아야 할 폴더인 models/index.js이다.

 

'use strict';

let sequelize;
if (config.use_env_variable) {
  seq....

// 생략

module.exports = db;

 

models/index.js와 config/config.json 살펴보기

index.js에서 config.json을 활용하기 때문에 코드를 잘 살펴보아야 한다. config.json 불러와 [env]에 설정한 값을 토대로 sequilize를 구성하므로 살펴보자. 한편, sequelize-cli에서 자동 생성한 models/index.js는 에러가 잦으므로 다음과 같이 변경해줍시다. (동작원리는 같습니다)

//index.js
import path from "path";
import Sequelize from "sequelize";

const env = process.env.NODE_ENV || "development"; //실제 출시할 때 production로 변경.
const config = require("../config/config.json")[env]; //config.json 객체에서 [env] 선택

const sequelize = new Sequelize(
  config.database,
  config.username,
  config.password,
  config
);

const db = {}; //db라는 객체를 만들고 모듈로 활용

db.Sequelize = Sequelize;
db.sequelize = sequelize;

export default db;
//config.json
{
  "development": {
    "username": "root",
    "password": null,
    "database": "database_development",
    "host": "127.0.0.1",
    "dialect": "mysql",
    "operatorsAliases": false
  },
  ... // 생략
}

 

Config 수정을 통해 MySQL과 연결하기

 

MySQL 설정 당시 입력한 비밀번호를 포함한 값들을 config.json에 입력한 후 app.js에 코드를 추가합니다.

// config.json
//config.json
{
  "development": {
    "username": "여기에 유저 이름을 적으세요",
    "password": "여기에 비밀번호를 적으세요",
    "database": "이용할 DB의 이름을 적으세요",
    "host": "설정한 호스트를 적으세요",
    "dialect": "mysql",
    "operatorsAliases": false
  },
  ... // 생략
}

전 다음과 같이 적었습니다.

{
  "development": {
    "username": "root", //제가 만든 계정 이름입니다.
    "password": "비밀번호", //제가 만든 비밀번호입니다
    "database": "nodejs", //제가 만든 DB 이름입니다.
    "host": "127.0.0.1", //제가 사용할 호스트입니다.
    "dialect": "mysql",
    "operatorsAliases": false,
    "logging": true // 이후 콘솔창에 로깅이 뜨는 게 싫다면 false로 바꿉시다
  }
}

app.js에는 다음을 추가합니다. models/index.js에서 export한 db를 불러온 후 다음과 같이 입력합니다. sync 메서드를 사용하면 알아서 MySQL과 연동됩니다.

import db from "./models/index";


db.sequelize.sync(); //sync 메서드를 사용하면 알아서 MySQL과 연동됨

 

sequelize를 통한 DB(schema), Table 생성

 

SQL에서는 다음과 같이 DB를 생성했습니다만

CREATE DATABASE [DB 명];

sequelize에서는 DB를 다음과 같이 생성합니다. config의 "database"에 입력한 DB가 생성됩니다. 위에서 nodejs를 입력했으므로 nodejs라는 DB가 생성 됐습니다.

sequelize db:create

 

Table을 생성하기 위해서는 sequelize를 통해 생성된 models 폴더에 테이블을 생성해주어야 합니다. 현재 models 폴더에는 index.js 하나만 있을 것입니다. 여기에 모델을 생성하도록 합시다. 저는 user.js, comment.js를 생성했습니다. 모델의 각 파일 하나는 MySQL의 테이블과 대응됩니다. 

 

다음과 같은 방식으로 테이블을 생성합니다. sequelize.define([테이블 명], [컬럼], [옵션])을 통해 테이블의 구조를 설계합니다.

// users 테이블
// 이름, 나이, 결혼, 자기소개, 생성일

module.exports = (sequelize, DataTypes) => {
  return sequelize.define(
    "user",
    {
      name: {
        type: DataTypes.STRING(20),
        allowNull: false,
        unique: true
      },
      age: {
        type: DataTypes.INTEGER.UNSIGNED,
        allowNull: false
      },
      married: {
        type: DataTypes.BOOLEAN,
        allowNull: false
      },
      comment: {
        type: DataTypes.TEXT,
        allowNull: true
      },
      created_at: {
        type: DataTypes.DATE,
        allowNull: false,
        defaultValue: sequelize.literal("now()")
      }
    },
    //timestamps는 생성일과 수정일, paranoid는 삭제일(복구용)입니다
    // charset과 collate를 다음과 같이 해야 한글이 깨지지 않습니다.
    { timestamp: false, underscored: true, charset: "utf8", collate: "utf8_general_ci" }
  );
};

 

index.js에는 다음을 추가합니다. 인자로 전달한 sequelize와 Sequelize가 앞서 user.js에 전달한 (sequelize, DataTypes)에 대응합니다.

//index.js
// 아래는 기존에 이미 있던 코드입니다.
// db.Sequelize = Sequelize; 시퀄라이즈 패키지
// db.sequelize = sequelize; 시퀄라이즈 인스턴스


db.User = require("./user")(sequelize, Sequelize);


// 최신 문법을 적용하고 싶다면 다음과 같이 합니다.
import user from "./user";
const user = user(sequelize, Sequelize);

 

 

 

관계 정의하기 (1: N)

RDBMS에 걸맞게 관계(relationship)는 DB에 빠질 수 없는 요소입니다. 1:1, 1:N(일대다), N:M(다대다) 등의 관계가 있으나 여기에서는 1:N을 사용해보겠습니다. 한 명의 유저가 여러 코멘트를 작성하는 상황을 가정해봅시다. comment 테이블의 commenter 열이 user 테이블의 id를 참조하게 코딩해봅시다.

 

//index.js

//db.User = require("./user")(sequelize, Sequelize);
//db.Comment = require("./comment")(sequelize, Sequelize);

db.User.hasMany(db.Comment, { foreingKey: "commenter", sourceKey: "id" });
db.Comment.belongsTo(db.User, { foreingKey: "commenter", targetKey: "id" });

 

코드를 보면 직관적으로 이해할 수 있습니다. user 테이블은 comment 테이블을 여러개 가지고 있습니다.(hasMany)

또한 comment 테이블은 user에 속해있습니다.(belongsTo)

새로 생성할 외래키로 foreignKey는 commenter이며 1:N의 관계에 따라 comment에 생성됩니다. 참고할 값은 user 테이블의 id입니다. (sourceKey, targetKey)

 

🚨 1:1, 1:N(일대다), N:M(다대다)
1:1 (hasOne, belongsTo)
1:N (hasMany, belongsTo)
N:M (belongsToMany)

 

관계 정의하기 (N: M)

//index.js
import path from "path";
import Sequelize from "sequelize";
import user from "./user";
import post from "./post";
import hashtag from "./hashtag";

const env = process.env.NODE_ENV || "development"; //실제 출시할 때 production로 변경.
const config = require("../config/config.json")[env]; //config.json 객체에서 [env] 선택

const sequelize = new Sequelize(
  config.database,
  config.username,
  config.password,
  config
);

const db = {}; //db라는 객체를 만들고 모듈로 활용

db.Sequelize = Sequelize;
db.sequelize = sequelize;

const User = user(sequelize, Sequelize);
const Post = post(sequelize, Sequelize);
const Hashtag = hashtag(sequelize, Sequelize);

// 1개의 User는 여러 개의 Post를 가지고 있는 1:N 관계
User.hasMany(Post);
Post.belongsTo(User);

// Post와 HashTag는 다대다 관계입니다.
// through에는 새로 생기는 모델(매칭 테이블)의 이름을 지정합니다.
Post.belongsToMany(Hashtag, { through: "PostHashTag" });
Hashtag.belongsToMany(Post, { through: "PostHashTag" });

// User 간 팔로우는 같은 테이블간 다대다입니다.
// as는 Join 작업시 사용하는 이름이며 foreignKey는 참고하는 외래키입니다.
// 팔로워는 팔로잉의 id를 참고하고 팔로잉은 팔로워의 id를 참고합니다.
User.belongsToMany(User, {
  through: "Follow",
  as: "Followers",
  foreignKey: "followingId"
});
User.belongsToMany(User, {
  through: "Follow",
  as: "Following",
  foreignKey: "followerId"
});

// User가 Like하는 Post는 다대다 관계입니다
User.belongsToMany(Post, { through: "Like" });
Post.belongsToMany(User, { through: "Like" });

export default db;

 

최종 실행!

npm start

 

SQL문으로 변환되어 잘 작동한다. workbench에서 확인할 수도 있다.

 

 

 


 

이렇게 만든 DB는 router 단계에서 다음과 같이 이용할 수 있다.

 

import express from "express";
import db from "../models/index"; //DB 임포트

const commentsRouter = express.Router();
const User = db.User; // 유저 테이블
const Comment = db.Comment; // 코멘트 테이블

commentsRouter.get("/:id", function(req, res, next) {
  Comment.findAll({
    include: {
      model: User,
      where: { id: req.params.id }
    }
  })
    .then(comments => {
      console.log(comments);
      res.json(comments);
    })
    .catch(err => {
      console.error(err);
      next(err);
    });
});


export default commentsRouter;

 

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체