...
Sequelize 란?
시퀄라이즈는 nodejs에서 데이터베이스를 쉽게 다룰 수 있도록 도와주는 라이브러리로, ORM(Object-relational Mapping)으로 분류된다.
sql 작성법을 모르더라도 데이터베이스 관리가 가능하다.
ORM이란 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑(연결)해주는 것을 말한다.
객체 지향 프로그래밍은 클래스를 사용하고, 관계형 데이터베이스는 테이블을 사용한다.
시퀄라이즈는 MySQL 외에도 MariaDB, PostgreSQL 등등 다른 데이터베이스에도 쓸 수 있다.
문법이 어느 정도 호환되므로 프로젝트를 다른 SQL 데이터베이스로 전환할 때도 편리하다.
시퀄라이즈는 자바스크립트 구문을 알아서 SQL로 바꿔준다.
그래서 자바스크립트만으로 MySQL을 조작할 수 있어, SQL 언어를 몰라도 MySQL을 어느 정도 다룰 수 있다는 장점이 있다.
시퀄라이즈 프로젝트 구성
시퀄라이즈에 필요한 morgan, sequelize, sequelize-cli, mysql2 패키지를 설치한다.
또, 개발 모드로 nodemon을 설치해주자.
$ npm i express morgan sequelize sequelize-cli mysql2
$ npm i -D nodemon
패키지를 설치했다먼 시퀄라이즈를 init하여 시퀄리이즈 구조를 생성한다.
$ npx sequelize init
명령 실행 이후에 폴더트리를 다시 보면 config, models, migrations, seeders 폴더가 생성된 것을 볼 수 있다.
추가적으로 우리가 프로젝트에 쓰일 폴더들도 직접 만들어주면 좋다. public, routes, views, app.js 등등
models 폴더 내의 index.js가 생성되었는지 확인한다.
sequelize-cli가 자동으로 생성해주는 코드는 그대로 사용할 때 에러가 발생하고, 필요없는 부분도 많으므로 다음과 같이 수정해준다.
models/index.js
const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development'; // 지정된 환경변수가 없으면 'development'로 지정
// config/config.json 파일에 있는 설정값들을 불러온다.
// config객체의 env변수(development)키 의 객체값들을 불러온다.
// 즉, 데이터베이스 설정을 불러온다고 말할 수 있다.
const config = require("../config/config.json")[env]
const db = {};
// new Sequelize를 통해 MySQL 연결 객체를 생성한다.
const sequelize = new Sequelize(config.database, config.username, config.password, config)
// 연결객체를 나중에 재사용하기 위해 db.sequelize에 넣어둔다.
db.sequelize = sequelize;
// 모듈로 꺼낸다.
module.exports = db;
config/config.json
위 코드의 models/index.js 파일에서 env 변수에 process.env.NODE_ENV 또는 'development'로 설정해 주었다.
process.env.NODE_ENV 환경변수를 따로 지정하지 않는한 변수env에 기본적으로 'development'가 오기 때문에, development의 환경 설정을 가져오게 된다.
추후 배포할 때는 process.env.NODE_ENV를 production으로 설정하면 된다.
시퀄라이즈 MySQL 연결
이제 시퀄라이즈를 통해 익스프레스 앱과 MySQL을 연결해보자.
app.js를 생성하여 익스프레스와 시퀄라이즈 연결코드를 다음과 같이 작성한다.
app.js
const express = require('express');
const path = require('path');
const morgan = require('morgan');
// index.js에 있는 db.sequelize 객체 모듈을 구조분해로 불러온다.
const { sequelize } = require('./models');
const app = express();
app.set('port', process.env.PORT || 3000);
// PUG 설정
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
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()); // json 파싱
app.use(express.urlencoded({ extended: false })); // uri 파싱
// 일부러 에러 발생시키기 TEST용
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 : {}; // 배포용이 아니라면 err설정 아니면 빈 객체
res.status(err.status || 500);
res.render('error'); // 템플릿 엔진을 렌더링 하여 응답
});
// 서버 실행
app.listen(app.get('port'), () => {
console.log(app.get('port'), '번 포트에서 대기 중');
});
[sequelize.sync() 옵션]
이제 npx nodemon app.js로 서버를 실행해보자.
위와 같은 메시지가 뜨면 성공이다.
연결에 실패한 경우 에러 메시지가 로깅된다.
에러는 주로 MySQL 데이터베이스를 실행하지 않았거나, 비밀번호를 틀렸거나, 설정 파일을 잘못 불러왔을 때 발생한다.
ERR_INVALID_ARG_TYPE
만일 다음과 같은 에러가 발생 한다면,
(node:16387) [SEQUELIZE0004] DeprecationWarning: A boolean value was passed to options.operatorsAliases. This is a no-op with v5 and should be removed.
internal/crypto/hash.js:70
throw new ERR_INVALID_ARG_TYPE('data',
^
TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be one of type string, Buffer, TypedArray, or DataView. Received type number
at Hash.update (internal/crypto/hash.js:70:11)
at sha1 (/Users/noel/Documents/project/node/node.js_book/6.1/learn-sequelize/node_modules/mysql2/lib/auth_41.js:31:8)
at Object.token [as calculateToken] (/Users/noel/Documents/project/node/node.js_book/6.1/learn-sequelize/node_modules/mysql2/lib/auth_41.js:65:18)
at new HandshakeResponse (/Users/noel/Documents/project/node/node.js_book/6.1/learn-sequelize/node_modules/mysql2/lib/packets/handshake_response.js:28:26)
at ClientHandshake.sendCredentials (/Users/noel/Documents/project/node/node.js_book/6.1/learn-sequelize/node_modules/mysql2/lib/commands/client_handshake.js:51:31)
at ClientHandshake.handshakeInit (/Users/noel/Documents/project/node/node.js_book/6.1/learn-sequelize/node_modules/mysql2/lib/commands/client_handshake.js:136:12)
at ClientHandshake.execute (/Users/noel/Documents/project/node/node.js_book/6.1/learn-sequelize/node_modules/mysql2/lib/commands/command.js:39:22)
at Connection.handlePacket (/Users/noel/Documents/project/node/node.js_book/6.1/learn-sequelize/node_modules/mysql2/lib/connection.js:408:32)
at PacketParser.onPacket (/Users/noel/Documents/project/node/node.js_book/6.1/learn-sequelize/node_modules/mysql2/lib/connection.js:70:12)
at PacketParser.executeStart (/Users/noel/Documents/project/node/node.js_book/6.1/learn-sequelize/node_modules/mysql2/lib/packet_parser.js:75:16)
at Socket.<anonymous> (/Users/noel/Documents/project/node/node.js_book/6.1/learn-sequelize/node_modules/mysql2/lib/connection.js:77:25)
at Socket.emit (events.js:210:5)
at addChunk (_stream_readable.js:308:12)
at readableAddChunk (_stream_readable.js:289:11)
at Socket.Readable.push (_stream_readable.js:223:10)
at TCP.onStreamRead (internal/stream_base_commons.js:182:23) {
code: 'ERR_INVALID_ARG_TYPE'
}
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! learn-sequelize@0.0.0 start: `node ./bin/www`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the learn-sequelize@0.0.0 start script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
npm ERR! A complete log of this run can be found in:
npm ERR! /Users/noel/.npm/_logs/2019-10-26T16_07_07_216Z-debug.log
config/config.json에서
password 가 "123456" 이어야 하는데 123456 인지 확인한다.
json은 무조건 문자열!!!
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.