ORM는 우리가 사용하는 프로그래밍 언어를 SQL문으로 변환해준다. python의 경우 장고 ORM, node.js 에는 type ORM, 시퀄라이즈(sequelize) 등이 존재한다. SQL문을 작성하지 않고 평소 하던 JS나 python으로 DB를 제어할 수 있어서 편하다. 그러나 ORM에 너무 의존하는 것은 좋지 않다. ORM에 문제가 생기거나 속도가 중요해질때는 SQL을 활용해야 한다. 결론은 ORM과 SQL 둘 다 배워야 한다는 것이다.
sequelize 설치
npm i sequelize
npm i -g sequelize-cli // sequelize를 터미널에서 사용하게 해줌
npm i mysql2 // mysql 사용을 위해 설치
sequelize 실행하기
sequelize init
config/config.json, models/index.js, migrations, seeders 폴더, 파일이 생성된다.
여기서 가장 중요하고 알아야 할 폴더인 models/index.js이다.
'use strict';
let sequelize;
if (config.use_env_variable) {
seq....
// 생략
module.exports = db;
models/index.js와 config/config.json 살펴보기
index.js에서 config.json을 활용하기 때문에 코드를 잘 살펴보아야 한다. config.json 불러와 [env]에 설정한 값을 토대로 sequilize를 구성하므로 살펴보자. 한편, sequelize-cli에서 자동 생성한 models/index.js는 에러가 잦으므로 다음과 같이 변경해줍시다. (동작원리는 같습니다)
//index.js
import path from "path";
import Sequelize from "sequelize";
const env = process.env.NODE_ENV || "development"; //실제 출시할 때 production로 변경.
const config = require("../config/config.json")[env]; //config.json 객체에서 [env] 선택
const sequelize = new Sequelize(
config.database,
config.username,
config.password,
config
);
const db = {}; //db라는 객체를 만들고 모듈로 활용
db.Sequelize = Sequelize;
db.sequelize = sequelize;
export default db;
//config.json
{
"development": {
"username": "root",
"password": null,
"database": "database_development",
"host": "127.0.0.1",
"dialect": "mysql",
"operatorsAliases": false
},
... // 생략
}
Config 수정을 통해 MySQL과 연결하기
MySQL 설정 당시 입력한 비밀번호를 포함한 값들을 config.json에 입력한 후 app.js에 코드를 추가합니다.
// config.json
//config.json
{
"development": {
"username": "여기에 유저 이름을 적으세요",
"password": "여기에 비밀번호를 적으세요",
"database": "이용할 DB의 이름을 적으세요",
"host": "설정한 호스트를 적으세요",
"dialect": "mysql",
"operatorsAliases": false
},
... // 생략
}
전 다음과 같이 적었습니다.
{
"development": {
"username": "root", //제가 만든 계정 이름입니다.
"password": "비밀번호", //제가 만든 비밀번호입니다
"database": "nodejs", //제가 만든 DB 이름입니다.
"host": "127.0.0.1", //제가 사용할 호스트입니다.
"dialect": "mysql",
"operatorsAliases": false,
"logging": true // 이후 콘솔창에 로깅이 뜨는 게 싫다면 false로 바꿉시다
}
}
app.js에는 다음을 추가합니다. models/index.js에서 export한 db를 불러온 후 다음과 같이 입력합니다. sync 메서드를 사용하면 알아서 MySQL과 연동됩니다.
import db from "./models/index";
db.sequelize.sync(); //sync 메서드를 사용하면 알아서 MySQL과 연동됨
sequelize를 통한 DB(schema), Table 생성
SQL에서는 다음과 같이 DB를 생성했습니다만
CREATE DATABASE [DB 명];
sequelize에서는 DB를 다음과 같이 생성합니다. config의 "database"에 입력한 DB가 생성됩니다. 위에서 nodejs를 입력했으므로 nodejs라는 DB가 생성 됐습니다.
sequelize db:create
Table을 생성하기 위해서는 sequelize를 통해 생성된 models 폴더에 테이블을 생성해주어야 합니다. 현재 models 폴더에는 index.js 하나만 있을 것입니다. 여기에 모델을 생성하도록 합시다. 저는 user.js, comment.js를 생성했습니다. 모델의 각 파일 하나는 MySQL의 테이블과 대응됩니다.
다음과 같은 방식으로 테이블을 생성합니다. sequelize.define([테이블 명], [컬럼], [옵션])을 통해 테이블의 구조를 설계합니다.
// users 테이블
// 이름, 나이, 결혼, 자기소개, 생성일
module.exports = (sequelize, DataTypes) => {
return sequelize.define(
"user",
{
name: {
type: DataTypes.STRING(20),
allowNull: false,
unique: true
},
age: {
type: DataTypes.INTEGER.UNSIGNED,
allowNull: false
},
married: {
type: DataTypes.BOOLEAN,
allowNull: false
},
comment: {
type: DataTypes.TEXT,
allowNull: true
},
created_at: {
type: DataTypes.DATE,
allowNull: false,
defaultValue: sequelize.literal("now()")
}
},
//timestamps는 생성일과 수정일, paranoid는 삭제일(복구용)입니다
// charset과 collate를 다음과 같이 해야 한글이 깨지지 않습니다.
{ timestamp: false, underscored: true, charset: "utf8", collate: "utf8_general_ci" }
);
};
index.js에는 다음을 추가합니다. 인자로 전달한 sequelize와 Sequelize가 앞서 user.js에 전달한 (sequelize, DataTypes)에 대응합니다.
//index.js
// 아래는 기존에 이미 있던 코드입니다.
// db.Sequelize = Sequelize; 시퀄라이즈 패키지
// db.sequelize = sequelize; 시퀄라이즈 인스턴스
db.User = require("./user")(sequelize, Sequelize);
// 최신 문법을 적용하고 싶다면 다음과 같이 합니다.
import user from "./user";
const user = user(sequelize, Sequelize);
관계 정의하기 (1: N)
RDBMS에 걸맞게 관계(relationship)는 DB에 빠질 수 없는 요소입니다. 1:1, 1:N(일대다), N:M(다대다) 등의 관계가 있으나 여기에서는 1:N을 사용해보겠습니다. 한 명의 유저가 여러 코멘트를 작성하는 상황을 가정해봅시다. comment 테이블의 commenter 열이 user 테이블의 id를 참조하게 코딩해봅시다.
//index.js
//db.User = require("./user")(sequelize, Sequelize);
//db.Comment = require("./comment")(sequelize, Sequelize);
db.User.hasMany(db.Comment, { foreingKey: "commenter", sourceKey: "id" });
db.Comment.belongsTo(db.User, { foreingKey: "commenter", targetKey: "id" });
코드를 보면 직관적으로 이해할 수 있습니다. user 테이블은 comment 테이블을 여러개 가지고 있습니다.(hasMany)
또한 comment 테이블은 user에 속해있습니다.(belongsTo)
새로 생성할 외래키로 foreignKey는 commenter이며 1:N의 관계에 따라 comment에 생성됩니다. 참고할 값은 user 테이블의 id입니다. (sourceKey, targetKey)
🚨 1:1, 1:N(일대다), N:M(다대다)
1:1 (hasOne, belongsTo)
1:N (hasMany, belongsTo)
N:M (belongsToMany)
관계 정의하기 (N: M)
//index.js
import path from "path";
import Sequelize from "sequelize";
import user from "./user";
import post from "./post";
import hashtag from "./hashtag";
const env = process.env.NODE_ENV || "development"; //실제 출시할 때 production로 변경.
const config = require("../config/config.json")[env]; //config.json 객체에서 [env] 선택
const sequelize = new Sequelize(
config.database,
config.username,
config.password,
config
);
const db = {}; //db라는 객체를 만들고 모듈로 활용
db.Sequelize = Sequelize;
db.sequelize = sequelize;
const User = user(sequelize, Sequelize);
const Post = post(sequelize, Sequelize);
const Hashtag = hashtag(sequelize, Sequelize);
// 1개의 User는 여러 개의 Post를 가지고 있는 1:N 관계
User.hasMany(Post);
Post.belongsTo(User);
// Post와 HashTag는 다대다 관계입니다.
// through에는 새로 생기는 모델(매칭 테이블)의 이름을 지정합니다.
Post.belongsToMany(Hashtag, { through: "PostHashTag" });
Hashtag.belongsToMany(Post, { through: "PostHashTag" });
// User 간 팔로우는 같은 테이블간 다대다입니다.
// as는 Join 작업시 사용하는 이름이며 foreignKey는 참고하는 외래키입니다.
// 팔로워는 팔로잉의 id를 참고하고 팔로잉은 팔로워의 id를 참고합니다.
User.belongsToMany(User, {
through: "Follow",
as: "Followers",
foreignKey: "followingId"
});
User.belongsToMany(User, {
through: "Follow",
as: "Following",
foreignKey: "followerId"
});
// User가 Like하는 Post는 다대다 관계입니다
User.belongsToMany(Post, { through: "Like" });
Post.belongsToMany(User, { through: "Like" });
export default db;
최종 실행!
npm start
SQL문으로 변환되어 잘 작동한다. workbench에서 확인할 수도 있다.
이렇게 만든 DB는 router 단계에서 다음과 같이 이용할 수 있다.
import express from "express";
import db from "../models/index"; //DB 임포트
const commentsRouter = express.Router();
const User = db.User; // 유저 테이블
const Comment = db.Comment; // 코멘트 테이블
commentsRouter.get("/:id", function(req, res, next) {
Comment.findAll({
include: {
model: User,
where: { id: req.params.id }
}
})
.then(comments => {
console.log(comments);
res.json(comments);
})
.catch(err => {
console.error(err);
next(err);
});
});
export default commentsRouter;
'DB, ORM > 🧊 MySQL' 카테고리의 다른 글
MySQL에서 SQL 파일 사용하기(source), SQL 내보내기 (0) | 2020.07.29 |
---|---|
mysql 패키지) connection pool의 필요성 및 생성 (0) | 2020.07.29 |
(Ubuntu) MySQL 설치 및 환경변수 설정과 접속 (0) | 2020.06.09 |
ORM 말고 SQL로 AWS RDS DB와 Express 웹 서버 연결 (0) | 2020.04.09 |
(Window) MySQL 8 설치 및 환경변수 설정과 접속 (0) | 2020.03.12 |