JS/Node.js

[node.js] MySQL과 nodejs 연동을 위해 sequelize를 사용해보았다

kth990303 2021. 4. 12. 22:28
반응형

오늘 또 오랜만에 node.js 공부를 하면서 먼가 새로운거를 배웠다.

(아직 나 또한 배우는 단계로 일기처럼 쓴 포스팅이니, 무언가 정보를 얻어가기엔 좋지 않은 포스팅일 수도 있다...)

 

바로 sequelize라는 것인데 이게 무엇이냐?

바로 Spring에서의 Mybatis, JPA와 같은 ORM 중 하나이다!

 

???: Mybatis, JPA? ORM? 뭔소리냐..?

 

필자도 잘 모르는데 자바 스프링 먼저 공부했다고 깝죽댄다고 생각할 수 있는데, 

혹시나 스프링 공부 먼저 한 사람들이 이 포스팅을 볼 때, 비유를 함으로써 더 이해하기 쉽게 설명하기 위함이었다.

 

Sequelize가 뭐냐면, 일종의 ORM으로

ORM 뜻을 먼저 설명하자면,

객체(Object)와 관계형 데이터베이스(관계)(Relation)를 연동, 매핑(Mapping)해주는 것이다.

그 중 sequelize는 nodejs와 sql을 사용할 때 이용되며,

sequelize를 이용하면 sql query문을 덜 사용하여 더 쉽게 데이터베이스와 연동하게 해준다.

 

한줄요약하면 mysql 연동을 우리에게 더 쉽게 다룰 수 있게 해준다는 거다.

 

이제 아래부터 내가 기억하기 위해 

공부한 내용을 기록하고, 그 아래에는 대강 느낀점이랑 일기를 쓸 것이다.

(공부한 내용은 재미없을 거니까 그냥 맨 밑으로 내려서 느낀점만 읽고 가도 매우 좋다 ㅎ)


Sequelize 설치

npm i express morgan nunjucks sequelize sequelize-cli mysql2

일단 위와 같이 sequelize, sequelize-cli, mysql2를 npm으로 설치하자.

여기서 주의할 점이, mysql2는 mysql을 npm으로 설치하는 것이 아닌, sequelize와 연동하기 위한 드라이버를 설치한다고 생각하면 된다.

 

그 외에

morgan은 요청에 대한 정보를 나타내주는 미들웨어, 

nunjucks는 템플릿 엔진, 

express는 웹 프레임워크로,

 

sequelize와 관련이 적다.

npx sequelize init

npm으로 설치가 완료되면

위와 같이 시퀄라이즈 init을 해주자.

 

참고로 npx는 npm과 비슷한 듯 다른 것으로 알고 있는데, 정확한 차이점을 모르겠다... 

npm의 단점을 개선시킨 거 같은데 그럼 npm은 왜 아직도 쓰는거지?

나중에 알게 되면 추가해야겠다.

 

아무튼 설치하면 아래와 같이 뭔가가 생길 것이다.

config, migrations, models, seeders가 생길 것이고,

app.js, public, routes, views는 내가 만든 것이다.


Sequelize로 테이블 생성

 

일단 먼저 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'), '번 포트에서 대기 중');
});

sequelize는 models에서 require하는 것을 볼 수 있는데,

models는 아까 npx sequelize init할 때 생성된 것을 기억하는가?

이 때 models는 mysql과의 연동 정보 및 테이블 정보를 담는다.

 

예를 들어 nodejs schema에 user, comment 이렇게 두 개의 테이블을 만든다고 하자.

테이블을 만드는 방법엔 세 가지가 있다.

  1. 명령 프롬프트 창에서 mysql 쿼리문으로 직접 create한다.
  2. workbench를 통해 table을 생성한다.
  3. javascript로 js파일을 생성하는 방법으로 table을 생성한다.

개인적으로 sequelize를 알기 전 나는 1번 방법을 선호했었는데,

nodejs sequelize를 배우면서 3번 방법을 써보기로 했다.

 

우선 models 폴더에 user.js, comment.js로 테이블을 생성하기 전에

자동으로 index.js가 있을 것이다.

const Sequelize = require('sequelize');

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

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

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

module.exports = db;

 

맨 처음엔 위와 같이 놓으면 된다고 하는데,

아직 정확한 의미는 모르겠다.

 

config 폴더로 연동 정보는 다 설정해놨을텐데 이 index.js의 정체는 무엇일까...

entity 설정인 것 같긴 한데ㅋㅋ 아직 너무 많이 부족하다.

(참고로 config 폴더의 config.json은 아래와 같다.)

{
  "development": {
    "username": "root",
    "password": "비밀번호",
    "database": "테이블명",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mysql"
  }
}

 

 

user.js는 아래처럼 작성하면 된다 (참고로 아직 테이블 관계 연결은 하지 않았다. 즉, comment.js와 연결을 아직 하지 않은 상태)

const Sequelize=require('sequelize');

module.exports=class User extends Sequelize.Model{
    static init(sequelize){
        return super.init({
            name:{
                type:Sequelize.STRING(20),
                allowNull:false,
                unique:true,
            },
            age:{
                type:Sequelize.INTEGER.UNSIGNED,
                allowNull:false,
            },
            married:{
                type:Sequelize.BOOLEAN,
                allowNull:false,
            },
            comment:{
                type:Sequelize.TEXT,
                allowNull:true,
            },
            created_at:{
                type:Sequelize.DATE,
                allowNull:false,
                defaultValue: Sequelize.NOW,
            },
        }, {
            sequelize,
            timestamps: false,
            underscored: false,
            modelName: 'User',
            tableName: 'users',
            paranoid: false,
            charset: 'utf8',
            collate: 'utf8_general_ci',
        });
    }
}

init 메소드로 테이블을 생성하는 건데,

잘 보면 첫번째 인자로 테이블 컬럼의 속성과 값을,

두번째 인자로 이것저것 기타 설정을 넣어줌을 알 수 있다.

 

두번째 인자에서 sequelize는 entity 설정 (.. 아니 근데 nodejs에서도 entity라 하나?)을 해주는 것이고,

timestamps: false는 현재 가입일자를 자동으로 now()로 해줄지 말지의 여부인데,

이 코드에선 이미 우리가 직접 만들었으므로 따로 timestamps 기능을 이용하지 않기로 했다.

underscored: false는 테이블 컬럼 명에 언더바 _ 를 사용하게 할지 말지의 여부인 듯 하다.

 

뭐 그 외에 이것저것 많은데, 솔직히 아직 많이 경험이 부족해 실감이 나지 않아 나중에 따로 추가해야될 것 같다.

comment.js도 user.js와 비슷하게 하면 된다.


Spring boot에서도 JPA라는 ORM때문에 배울 게 엄청나게 많은데,

node.js에서도 sequelize라는 ORM이 있을 줄이야.

하긴 오히려 없는게 이상한건가?ㅋㅋㅋㅋ

 

백준 포스팅도 밀리고

스프링도 공부해야되고

디자인패턴 책도 읽어야되고

네트워크 공부도 해야되는데!

 

할게 너무 많다 ㅎㅎㅎ

생각해보니까 일기는 그냥 다른 포스팅에 써야지

반응형