백앤드/Node.js

[포스코x코딩온] 웹개발자 입문 과정 6주차 | Sequelize

영최 2023. 4. 10. 15:33
728x90

1.Sequelize란?

 ORM 라이브러리 중 하나로, 객체 지향 패러다임을 이용해서

 관계형 데이터 베이스 (RDB)의 데이터를 조작한다.

 *ORM: Object Relational Mapping

 (자바스크립트 구문 -> sql 로 변환하는 역할을 한다.)

 따라서 sql문을 대체한다고 생각하면 된다.

 Sequelize는 많은  MySQL을 포함한 많은 RDBMS를 지원하고,

 Promise 기반이므로 비동기 처리가 쉽다.

 

2.Sequelize 설치 방법

#1.sequelize 설치
npm install sequelize sequelize-cli mysql2
# * sequelize: sequelize 패키지
# * sequelize-cli: sequelize 명령어를 사용해 데이터베이스 작업을 할 수 있는 툴
# * mysql2: mysql과 sequelize를 연결하는 드라이버(도구)

#2.프로젝트 초기화 (폴더 구조 생성)
npx sequelize init
# * npx는 npm 레지스트리에 올라가있는 패키지를 쉽게 설치하고 관리할 수 있도록 도와주는 CLI 도구
# 몇몇 새로운 폴더가 생성됨

 새로 생성된 폴더 중에 'migration', 'seeders'를 삭제하면 폴더 구조는 다음과 같다.

'config'폴더와 'models'폴더가 새로 생성되었다.

 

프로젝트 폴더 구조

 

 

3.Sequelize 사용 방법 (sql문과 비교)

 가.config/config.json

  - development: 개발 환경

  - test: 테스트 환경

  - production: 배포 환경

{
  "development": {
    "username": "user",
    "password": "1234",
    "database": "codingon",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "test": {},
  "production": {}
}

  개발 환경으로  값을 세팅한다.

  • "username": mysql 아이디
  • "password":  mysql 비밀번호
  • "database": 사용하고자 하는 mysql 데이터 베이스 이름
  • "host": "127.0.0.1", DB 주소로 localhost 와 같다.
  • "dialect": 각 DB마다 고유 기능을 사용할 때 정의한다.

 

 나.models

   1)models/index.js

//models.index.js -> 'index'는 폴더를 대표하는 파일
//sequelize-cli 자동 생성 코드를 수정 한 것임

//1. sequelize 모듈 불러오기
const Sequelize = require("sequelize");

//2. config.json파일에서 개발 환경일 때의 db 설정 옵션을 가져옴
const config = require(__dirname + "/../config/config.json")["development"];
// - 출력 -
// {
//   "development": {
//     "username": "user",
//     "password": 1234,
//     "database": "codingon",
//     "host": "127.0.0.1",
//     "dialect": "mysql"
// }

//3. db 라는 이름의 빈 객체 정의
//(다른 파일에서 사용할 수 있도록 내보내려는 값)
const db = {};

//4. sequelize 객체 선언 시 매개변수로 db명, user명, 비번, 정보전체를 넘겨줌
const sequelize = new Sequelize(
  config.database,
  config.username,
  config.password,
  config
);

//5. db = { sequelize: sequelize, Sequelize: Sequelize}
db.sequelize = sequelize;
db.Sequelize = Sequelize;

//6. models 안 다른 파일 연결 db = { sequelize: sequelize, Sequelize: Sequelize, Visitor : 'xx'}
db.Visitor = require("./Visitor")(sequelize, Sequelize);

//7. 내보내기
module.exports = db;

   2)models/Visitor.js

Sequelize) models/Visitor.js mysql) model/Visitor.js.
 모델만 정의 및 exports sql문으로 작성
//1. visitor 모델 (-> 테이블 구조 ) 정의

const Visitor = function (Sequelize, DataTypes) {

  const model = Sequelize.define(
    //params1: 모델(테이블) 이름 설정
    "visitor",
    //params2: 컬럼 정의
    {
      id: {
        type: DataTypes.INTEGER,
        allowNull: false,
        primaryKey: true,
        autoIncrement: true,
      },
      name: {
        type: DataTypes.STRING(10),
        allowNull: false,
      },
      comment: {
        type: DataTypes.TEXT("medium"),
      },
    },

    // params3: 모델 옵션 정의
    {
      tableName: "visitor", //실제 mysql 테이블 명
      freezeTableName: true, //테이블 명 고정
      timestamps: false, // 데이터가 추가/수정되는 시간을 컬럼으로 만들어서 기록
    }
  );
  return model;
};

//2. 내보내기 (indexs에서 사용됨  require("./Visitor")(sequelize, Sequelize))
module.exports = Visitor;
const mysql = require("mysql");


// database 연결
const conn = mysql.createConnection({
  host: "localhost", 
  user: "user", 
  password: "1234", 
  database: "codingon", 
});

// (2) GET /visitor
exports.getVisitors = (callback) => {
  const sql = "SELECT * FROM visitor;";
  conn.query(sql, (err, rows) => {
    if (err) {
      throw err;
    }
    console.log("2. Visitor.js >> ", rows);
    callback(rows);
  });
};

// (3)POST /visitor/write
exports.postVisitor = (data, callback) => {
  const sql = `insert into visitor(name, comment) values('${data.name}', '${data.comment}');`;
  conn.query(sql, (err, rows) => {
    if (err) {
      throw err;
    }
    callback(rows.insertId);
  });
};

// (4) 삭제 DELETE /visitor/delete
exports.deleteVisitor = (id, callback) => {
  const sql = `delete from visitor where id=${id};`;
  conn.query(sql, (err, rows) => {
    if (err) {
      throw err;
    }
    callback(true);
  });
};

// (5) 수정  GET /visitor/get
exports.getVisitor = (id, callback) => {
  const sql = `select * from visitor where id=${id};`;
  conn.query(sql, (err, rows) => {
    if (err) {
      throw err;
    }
    callback(rows[0]); 
  });
};

// (6) 수정  PATCH  /visitor/edit
exports.patchVisitor = (data, callback) => {
  const sql = `update visitor set  name='${data.name}', comment='${data.comment}' where id=${data.id};`;
  conn.query(sql, (err, rows) => {
    if (err) {
      throw err;
    }
    callback();
  });
};

   Sequelize 모델 정의 시 두번째 파라미터 값(컬럼 정의)

   에서 사용하는 속성은 다음과 같다.

  • "type": 데이터 타입 정의
  • "primaryKey": 기본키 설정
  • "autoincrement":  숫자 자동 증가
  • "allowNull": NOT NULL 허용 여부
  • "comment": column에 대한 설명을 작성한다.
  • "validate": 데이터 유효성 검사

 

 .controller/Cvisitor.js

Sequelize) controller/CVisitor.js -> squelize문 작성 mysql) controller/CVisitor.js. -> model/Visitor 불러옴
//models/index.js 불러옴
const models = require("../models");

// (1) GET /
exports.main = (req, res) => {
  res.render("index");
};

// (2) 조회 GET /visitor
exports.getVisitors = async (req, res) => {
  const result = await models.Visitor.findAll();
  res.render("visitor", { data: result });
};

// (3) 생성 POST /visitor/write async/await
exports.postVisitor = async (req, res) => {
  const result = await models.Visitor.create({
    name: req.body.name,
    comment: req.body.comment,
  });
  res.send(result);
};

// (4) 삭제 DELETE /visitor/delete
exports.deleteVisitor = async (req, res) => {
  await models.Visitor.destroy({
    where: { id: req.body.id },
  });
  res.end();
};

// (5) 하나 조회(수정을 위한)  GET /visitor/get
exports.getVisitor = async (req, res) => {
  const result = await models.Visitor.findOne({
    where: { id: req.query.id },
  });
  res.send(result);
};

// (5)-4 수정  PATCH  /visitor/edit
exports.patchVisitor = async (req, res) => {
  const result = await models.Visitor.update(
    {
      name: req.body.name,
      comment: req.body.comment,
    },
    {
      where: { id: req.body.id },
    }
  );
  res.end();
};
//model/Visitor 불러옴
const Visitor = require("../model/Visitor");

// (1) GET /
exports.main = (req, res) => {
  res.render("index");
};

// (2) 조회 GET /visitor
exports.getVisitors = (req, res) => {
  Visitor.getVisitors((result) => {
    res.render("Visitor", { data: result });
  });
};

// (3) 생성 POST /visitor/write
exports.postVisitor = (req, res) => {
  Visitor.postVisitor(req.body, (result) => {
    res.send({ id: result, name: req.body.name, comment: req.body.comment });
  });
};

// (4) 삭제 DELETE /visitor/delete
exports.deleteVisitor = (req, res) => {
  Visitor.deleteVisitor(req.body.id, (result) => {
    res.send("삭제 성공!!");
  });
};

// (5) 조회(수정을 위한)  GET /visitor/get
exports.getVisitor = (req, res) => {
  Visitor.getVisitor(req.query.id, (result) => {
    res.send(result); 
  });
};

// (5)-4 수정  PATCH  /visitor/edit
exports.patchVisitor = (req, res) => {
  Visitor.patchVisitor(req.body, () => {
    res.send("수정 성공!");
  });
};

  Data Definit 으로 표시된 부분이 대응되는 부분이다.

 

 sql문을 작성할 때는 model에서 직접 sql문을 작성한 뒤 controller에서 값을 불러왔다면,

 Sequelize를 사용할 때는

 model -> sequelize 모델 정의

 controller-> sequelize 쿼리문으로 값을 db에서 불러온다는 차이가 있다.

 

또한 promise 기반이므로 .then(), async-await 둘 다 가능하다. 

 

 Sequelize 쿼리문은 다음과 같다. 

  • findAll(): 전체 조회
  • findOne(): 하나 조회
  • create(): 생성(삽입)
  • update(): 수정
  • destroy(): 삭제

 

 

4.Sequelize 전체 코드

https://github.com/jayoung977/web/tree/main/BackEnd/20230408/14_sequelize

728x90