[ORM] ๐ ์ํ๋ผ์ด์ฆ ์ด๊ธฐ ๊ตฌ์ฑ & DB ์ฐ๊ฒฐ (MySQL)
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์ ๋ฌด์กฐ๊ฑด ๋ฌธ์์ด!!!