개발 공부한 것들/SeSSAC 웹 풀스텍 과정 회고록

[SeSSAC] 웹 풀스택 영등포 5기 과정_sequelize

geograp 2023. 9. 3. 19:59

이번 시간에는 sequelize에 대해 배운 것을 정리했습니다.

 

저희가 mvc 패턴에서 model을 통해 DB에 접근하였습니다.

이 model폴더에서 저희가 한 sql query는 사실 굉장히 간단한 버전이었기 때문에

model에서 직접 접근을 한 것이었고, 실제로 현업에서는 sql문이 복잡하기 때문에

그 복잡한 sql query문을 간략하게 해주고, 쉽게 접근할 수 있게 한 장치가 sequelize입니다.

 

 

 

0. sequelize

SQL 쿼리를 더 가독성 있고 간단하게 작성할 수 있도록 도와주는

Node.js 기반의 ORM (Object-Relational Mapping) 라이브러리입니다.

자바스크립트 구문을 알아서 sql 구문으로 변환시켜주는 똑똑한 아이 입니다.

 

sequelize를 쓴다면, [유지보수 용이, 가독성 향상, 데이터 유효성 검사 등] 많은 이점을 얻을 수 있습니다.

 

저희는 하기와 같은 명령어로 sequelize를 설치하였습니다.

npm install sequelize sequelize-cli mysql2
  • sequelize: 시쿼라이즈 패키지
  • sequelize-cli: 시퀄라이즈 명령어를 실행
  • mysql2: mysql과 시퀄라이즈를 연결하는 드라이버(도구)

 

이렇게 npm 설치를 한다면, 새로운 파일과 폴더들이 생성됩니다. (models, config ...)


1. sequelize 세팅하기(models파일 내 index.js)

 

새로 생긴 models폴더 index.js 먼저 보도록 하겠습니다.

(sequelize를 가져오는 부분)

'use strict';

const Sequelize = require('sequelize');
const config = require(__dirname + '/../config/config.json')['development'];

const sequelize = new Sequelize(
  config.database, // sessac2
  config.username, // user
  config.password, // 1234
  config
  );
  
const db = {};
db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.Visitor = require('./Visitor')(sequelize, Sequelize);

module.exports = db;

일단 저희는 개념을 익혀야 하기 때문에 비교적 선언이 짧습니다. 

한줄한줄 보면서 어떤 의미인지 알아가보도록 하죠 ㅠㅠ


'use strict';

JavaScript strict mode를 활성화하는 선언으로,

코드에 오류를 더 잘 드러나게 하고 안전성을 높이는 데 도움이 됩니다.

 

const Sequelize = require('sequelize');

sequelize 모듈을 불러와서 Sequelize라는 변수에 모듈을 넣습니다.

 

const config = require(__dirname + '/../config/config.json')['development'];

config.json 파일에서 'development' 환경에 해당하는 데이터베이스 설정을 불러와 config 변수에 저장합니다.

이 설정은 데이터베이스와 연결 정보와 관련된 모든 것입니다.

 

const sequelize = new Sequelize(
  config.database, // sessac2
  config.username, // user
  config.password, // 1234
  config
  );

앞서 선언한 Sequelize모듈로 "sequelize" 변수에 새로운 Sequelize를 넣습니다.

새로운 시퀄라이즈를 만드는데에 필요한 정보들은

앞서 가져왔던 config모듈 내의 여러 정보들을 부릅니다.

 

const db = {};
db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.Visitor = require('./Visitor')(sequelize, Sequelize);

처음에 빈 db 객체를 생성합니다.

이 db 객체에 방금 전 새로 만들었던 sequelize를 넣고, Sequelize로 시퀄라이즈 모듈도 넣습니다.

그리고 Visitor라는 모듈을 불러와서 Visitor 내에 있는 sequelize와 Sequelize를 넣고 Visitor를 넣습니다.

 

마지막 줄인 db.Visitor 에 대한 이해가 조금 걸렸는데, 

db.Visitor에 Visitor모듈을 불러올 때 저희가 인자값으로 sequelize와 Sequelize가 필요하도록

설계를 해서 선언과 동시에 정의하고 있어서 그렇습니다.

 

그럼, 저희 models폴더 내의 Visitor파일을 보도록 하겠습니다.

 

 

 

2. models파일 내 Visitor.js

 

바로 앞 전에 보았던 db에 넣은 Visitor모듈입니다.

여기서 Visitor에 Sequelize와 DataTypes를 받도록 되어있습니다.

이에 맞게 저희는 sequelize와 Sequelize를 넣은 것입니다!

const Visitor = (Sequelize, DataTypes) => {
    const model = Sequelize.define('visitor', {
        id: {
            type: DataTypes.INTEGER,
            allowNull: false,
            primaryKey: true,
            autoIncrement: true,
        },
        name : {
            type: DataTypes.STRING(10),
            allowNull: false,
        },
        comment: {
            type: DataTypes.TEXT('medium'),
        }
    }, {
        tableName: 'visitor', // 실제 db 테이블명
        freezeTableName: true,
        timestamps: false,
    });
    return model;
};

module.exports = Visitor;

 

보시면 Visitor모듈 내에 model이 define되어있습니다.

 

sequelize.define은 데이터베이스의 테이블을 정의하는 메서드입니다.

이 메서드의 형태는 아래와 같습니다.

sequelize.define(modelName, attributes, options);
  • modelName: 정의하고자 하는 테이블 명 ('visitor')
  • attributes: 테이블의 속성을 정의하는 객체
  • options: 테이블 객체의 속성 이름이나 데이터 유형 및 제약 조건을 명시

 

유독 중요하고 긴 attributes을 떼와서 보면 type, allowNull, primaryKey 등으로

여러가지 db의 속성 조건을 걸고 있습니다.

	id: {
            type: DataTypes.INTEGER,
            allowNull: false,
            primaryKey: true,
            autoIncrement: true,
        },
        name : {
            type: DataTypes.STRING(10),
            allowNull: false,
        },
        comment: {
            type: DataTypes.TEXT('medium'),
        }

 

그리고 option부분도 db에 대한 정보와 제약조건을 가지고 있습니다.

{
        tableName: 'visitor', // 실제 db 테이블명
        freezeTableName: true,
        timestamps: false,
}

이렇게 하면, 저희가 원하는 DB연결을 한 sequelize 객체인 Visitor모델이 만들어집니다!

 

 

3. sequelize를 controller에 활용하기

 

전에 만들었던 model폴더 대신에 (npm으로 저절로 생성된) models폴더로 DB연결을 하여,

controller에서 직접 DB query를 작성할 수 있게 되었습니다.

 

저희는 수업시간에 이를 이용하여 controller를 refactoring하였습니다.

 

여기서 sequelize의 sql문 작성법을 기초적으로 배웠습니다.

 

 3-1. findAll()

exports.visitor = async (req, res) => {
  // [before]
  // Visitor.getVisitors((result) => {
  //   res.render('visitor', { data: result });
  // });
  const result = await Visitor.findAll()
  res.render('visitor', { data: result });
};

 

3-2. findOne()

exports.getVisitor = async(req, res) => {
    // [ before ]
    // const{id} = req.params;
    // Visitor.getVisitor(id, (result) => {
    //     res.send(result);
    // });
    const { id } = req.params;
    const result = await Visitor.findOne({
      where: {id: id}
    });
    res.send(result);
};

 

3-3. create()

exports.postVisitor = async (req, res) => {
  // [before]
  // console.log('req.body = ', req.body);
  // Visitor.postVisitor(req.body, (insertId) => {
  //   const { name, comment } = req.body;
  //   res.send({ id: insertId, name, comment });
  // });
  const { name, comment } = req.body;
  const result = await Visitor.create({
  	name,
    comment,
  });
  res.send(result);
};

 

3-4. update()

exports.updateVisitor = async(req, res) => {
  // [ before ]
  // console.log(req.body);
  // Visitor.updateVisitor(req.body, (result) => {
  //   res.send({ isUpdated: true });
  // });

  // update( {변경될 값}, {where절})
  const result = await Visitor.update({
    name: req.body.name,
    comment: req.body.comment,
  }, {
    where: {id: req.body.id}
  });
  res.send({isUpdated: true});
};

 

3-5. destory()

exports.deleteVisitor = async (req, res) => {
  // [ before ]
  // const { id } = req.body;
  // Visitor.deleteVisitor(id, (result) => {
  //   res.send(result); // res.send(true)
  // });
  const { id } = req.body;
  const result = await Visitor.destroy({
    where: { id: id },
  });
  res.send(true);
};