[Node.js] 6-2. MySQL (Sequelize ORM)

Seohyun-kim·2022년 4월 29일
0

Node.js

목록 보기
12/12
post-thumbnail

시퀄라이즈


1. 시퀄라이즈 ORM

  • SQL 작업을 쉽게 할 수 있도록 도와주는 라이브러리
    • ORM: Object Relational Mapping: 객체와 데이터를 매핑(1대1 짝지음)
    • MySQL 외에도 다른 RDB(Maria, Postgre, SQLite, MSSQL)와도 호환됨
    • 자바스크립트 문법으로 데이터베이스 조작 가능
  • 예제

2. 시퀄라이즈 CLI 사용하기

  • 시퀄라이즈 명령어 사용하기 위해 sequelize-cli 설치
    • mysql2는 MySQL DB가 아닌 드라이버(Node.js와 MySQL을 이어주는 역할)
  • npx sequelize init으로 시퀄라이즈 구조 생성

3. models/index.js

const Sequelize = require('sequelize');

const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};

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

db.sequelize = sequelize;

module.exports = db;

4. MySQL 연결하기 (app.js)

const express = require('express');
const path = require('path');
const morgan = require('morgan');
const nunjucks = require('nunjucks');

const { sequelize } = require('./models');

const app = express();
app.set('port', process.env.PORT || 3001);
app.set('view engine', 'html');
nunjucks.configure('views', {
  express: app,
  watch: true,
});
sequelize.sync({ force: false }) //⭐
  .then(() => {
    console.log('데이터베이스 연결 성공');
  })
  .catch((err) => {
    console.error(err);
  });

app.use(morgan('dev'));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));

app.use((req, res, next) => {
  const error =  new Error(`${req.method} ${req.url} 라우터가 없습니다.`);
  error.status = 404;
  next(error);
});

app.use((err, req, res, next) => {
  res.locals.message = err.message;
  res.locals.error = process.env.NODE_ENV !== 'production' ? err : {};
  res.status(err.status || 500);
  res.render('error');
});

app.listen(app.get('port'), () => {
  console.log(app.get('port'), '번 포트에서 대기 중');
});

5. DB 연결 정보 설정 (config.json)

{
  "development": {
    "username": "root",
    "password": "nodejsbook",
    "database": "nodejs",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
...
}

6. 연결 테스트

  • npm start로 실행해서 SELECT 1+1 AS RESULT가 나오면 연결 성공

7. 모델 생성

  • 테이블에 대응되는 시퀄라이즈 모델 생성
    const Sequelize = require('sequelize');
    
    module.exports = class User extends Sequelize.Model {
      static init(sequelize) {
        return super.init({
    
    			// 시퀄라이즈는 id를 자동으로 넣어주기 때문에 생략 가능!!!
    
          name: {
            type: Sequelize.STRING(20),
            allowNull: false,
            unique: true,
          },
          age: {
            type: Sequelize.INTEGER.UNSIGNED,
            allowNull: false,
          },
          married: {
            type: Sequelize.BOOLEAN, //true, false
            allowNull: false,
          },
          comment: {
            type: Sequelize.TEXT,
            allowNull: true,
          },
          created_at: {
            type: Sequelize.DATE, 
    				// 시퀄라이즈에서 DATA는 MySQL에서 DATETIME
    				//               DateOnly          DATE
    
            allowNull: false,
            defaultValue: Sequelize.NOW,
          },
        }, {
          sequelize,
          timestamps: false,
          underscored: false,
          modelName: 'User',
          tableName: 'users',
          paranoid: false,
          charset: 'utf8',
          collate: 'utf8_general_ci',
        });
      }
    
      static associate(db) {
        db.User.hasMany(db.Comment, { foreignKey: 'commenter', sourceKey: 'id' });
      }
    };

8. 모델 옵션들

  • 시퀄라이즈 모델의 자료형은 MySQL의 자료형과 조금 다름
  • define 메서드의 세 번째 인자는 테이블 옵션
    • timestamps: true면 createdAt(생성 시간), updatedAt(수정 시간) 컬럼을 자동으로 만듦
      • 예제에서는 직접 created_at 컬럼을 만들었으므로 false로 함
    • paranoid 옵션은 true면 deletedAt(삭제 시간) 컬럼을 만듦, 로우 복구를 위해 * 완전히 삭제하지 않고 deletedAt에 표시해둠
    • underscored 옵션은 캐멀케이스로 생성되는 컬럼을 스네이크케이스로 생성
    • modelName은 모델 이름, tableName 옵션은 테이블 이름을 설정
    • charset과 collate는 한글 설정을 위해 필요(이모티콘 넣으려면 utf8mb4로)

9. 댓글 모델 생성

const Sequelize = require('sequelize');

module.exports = class Comment extends Sequelize.Model {
  static init(sequelize) {
    return super.init({
      comment: {
        type: Sequelize.STRING(100),
        allowNull: false,
      },
      created_at: {
        type: Sequelize.DATE,
        allowNull: true,
        defaultValue: Sequelize.NOW,
      },
    }, {
      sequelize,
      timestamps: false,
      modelName: 'Comment',
      tableName: 'comments',
      paranoid: false,
      charset: 'utf8mb4',
      collate: 'utf8mb4_general_ci',
    });
  }

  static associate(db) {
    db.Comment.belongsTo(db.User, { foreignKey: 'commenter', targetKey: 'id' });
  }
};

10. 댓글 모델 활성화

  • index.js에 모델 연결
    • init으로 sequelize와 연결

    • associate로 관계 설정

      const Sequelize = require('sequelize');
      const User = require('./user');
      const Comment = require('./comment');
      
      ...
      const sequelize = new Sequelize(config.database, config.username, config.password, config);
      
      db.sequelize = sequelize;
      
      db.User = User;
      db.Comment = Comment;
      
      User.init(sequelize);
      Comment.init(sequelize);
      
      User.associate(db);
      Comment.associate(db);
      
      module.exports = db;

11. 관계 정의하기

  • users 모델과 comments 모델 간의 관계를 정의
    • 1:N 관계 (사용자 한 명이 댓글 여러 개 작성)
    • 시퀄라이즈에서는 1:N 관계를 hasMany로 표현(사용자.hasMany(댓글))
    • 반대의 입장에서는 belongsTo(댓글.belongsTo(사용자))
    • belongsTo가 있는 테이블에 컬럼이 생김(댓글 테이블에 commenter 컬럼)


11-1. 1대 1 관계

  • 예) 사용자 테이블과 사용자 정보 테이블

11-2. N대 M 관계

  • 예) 게시글과 해시태그 테이블

하나의 게시글이 여러 개의 해시태그를 가질 수 있고 하나의 해시태그가 여러 개의 게시글을 가질 수 있음

  • DB 특성상 다대다 관계는 중간 테이블이 생김


12. 시퀄라이즈 쿼리

윗 줄이 SQL문, 아랫 줄은 시퀄라이즈 쿼리(자바스크립트)

시퀄라이즈 쿼리 예시

13. 관계 쿼리

관계 쿼리 예시


14. raw 쿼리

  • 직접 SQL을 쓸 수 있음


인프런 Node.js 강의
Zerocho 님의 "Node.js 교과서 - 기본부터 프로젝트 실습까지" 강의를 기반으로 작성한 문서입니다.

0개의 댓글