✔ 사전적 의미 : 속편화 하다. 후속작을 만들다.
✔ 공식 홈페이지의 설명(https://sequelize.org/)
Sequelize는 Postgres, MySQL, MariaDB, SQLite 및 SQL Server 등을 위한 최신 TypeScript 및 Node.js ORM입니다.
견고한 트랜잭션 지원, 관계, 열망 및 지연 로딩, 읽기 복제 등을 제공합니다.
ORM(Object Relational Mapping)
- 객체 지향 프로그래밍 언어 를 사용하여 호환되지 않는 유형 시스템 간에 데이터를 변환 하는 프로그래밍 기술
- 여기서는 객체와 RDBMS의 데이터를 자동으로 연결해주는 것 즉, ORM을 통해 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 객체 지향적인 코드를 생산할 수 있다.
✔ Sequlize 왜 적용하려고 하는데?
- 여러가지 API를 만들면서 코드가 길어지고 쿼리문도 많이 늘어났다. user에 대한 model 폴더를 만들어 쿼리문만 따로 분류 했는데 분류를 해도 뭐가 뭔지 모르겠다. 이에 좀 더 직관적인 코드를 구현할 방법이 필요했다.
- 장점 : 실제로 Sequelize를 이용해보니 쿼리를 메서드와 값으로 표현할 수 있어 텍스트로 쿼리를 직접 작성하는 것 보다 코드를 작성하거나 읽기 더 쉬워졌다.
- 단점 : 쿼리가 복잡해지는 부분(서브쿼리) 적용하기가 어려웠다. 프로젝트가 복잡해질 경우 오히려 사용하는 난이도가 올라걸거 같다.
✔ 어떻게 적용 했는데?
1. 설치
npm i --save sequelize
2. 설정파일 적용하기(기존에 mysql connection 하기 위해 썼던 설정을 그대로 썼다)
//setting_config.js
require('dotenv').config();
const config = {
development: { //로컬 db를 바라본다.
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PW,
port: process.env.DB_PORT,
database: process.env.DB_NAME,
multipleStatements: true,
dateStrings: 'date' //mysql의 data 타입을 깔끔하게 바꿔줌
},
/*
...
test 환경의 DB 설정(생략)
...
*/
};
// 생성한 객체를 모듈화 하여 외부 파일에서 불러와 사용 할 수 있도록
module.exports = config;
3. 모델 생성하기
//User모델 user.js
module.exports = (sequelize, Sequelize) => {
return sequelize.define("users", {
idx: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false
},
id: {
type: Sequelize.STRING(20),
allowNull: false, // == not null
// primaryKey: true,
},
password: {
type: Sequelize.STRING(255),
allowNull: false,
},
salt: {
type: Sequelize.STRING(255),
allowNull: false,
},
name: {
type: Sequelize.STRING(10),
allowNull: false
},
email: { //char(50)
type: Sequelize.STRING(50),
allowNull: false
},
user_photo: { //varchar(200)
type: Sequelize.STRING(200),
allowNull: true
},
}, {
charset: "utf8", // 한국어 설정 utf8mb4 쓰면 이모티콘도 가능
collate: "utf8_general_ci", // 한국어 설정
tableName: "user_table", // 테이블 이름 정의
timestamps: true, // createAt, updateAt 활성화
paranoid: true, // deleteAt 옵션
});
};
//Post 모델 post.js
module.exports = (sequelize, Sequelize) => {
return sequelize.define("posts", {
idx: {
type: Sequelize.INTEGER,
primaryKey: true,
unique: true,
autoIncrement: true,
allowNull: false
},
user_idx: {
type: Sequelize.INTEGER, // The data type defined here and
allowNull: false,
references: {
model: 'users',
key: 'idx'
},
},
title: {
type: Sequelize.STRING(255),
allowNull: false,
},
content: {
type: Sequelize.TEXT,
allowNull: false
},
view_post_count: {
type: Sequelize.INTEGER,
allowNull: false,
defaultValue: 0
},
}, {
charset: "utf8mb4", // 한국어 설정 utf8mb4 쓰면 이모티콘도 가능
collate: "utf8mb4_general_ci", // 한국어 설정
tableName: "post_table", // 테이블 이름 정의
timestamps: true, // createAt, updateAt 활성화
paranoid: true, // deleteAt 옵션
});
};
4. /model/index.js에 모델 선언 관계 적용하기
const fs = require('fs');
const path = require('path');
const Sequelize = require('sequelize');
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || 'development';
const config = require('../config/setting_config.js')[env];
//env 설정되어있는 폴더
const db = {};
let sequelize;
//DB연결
if (config.use_env_variable) {
sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
sequelize = new Sequelize(config.database, config.user, config.password,
{
host: config.host,
port: config.port,
dialect: config.dialect,
operatorsAliases: 0,
timezone: "+09:00", // DB에 저장할 때 시간 설정
dialectOptions: {
timezone: "+09:00", // DB에서 가져올 때 시간 설정
}
}
);
}
db.sequelize = sequelize;
db.Sequelize = Sequelize;
db.user = require('./user.js')(sequelize, Sequelize);
db.post = require('./post.js')(sequelize, Sequelize);
//테이블의 관계 지정
//User와 Post의 관계 하나의 유저가 여러 post(게시글)을 가진다.
db.user.hasMany(db.post, {
foreignKey: 'user_idx',
sourceKey: 'idx'
});
db.post.belongsTo(db.user, {
foreignKey: 'user_idx',
targetKey: 'idx'
});
5. app.js에서sequelize sync 코드 추가
const express = require('express');
const app = express();
app.listen(port1, function () {
console.log('app listening on port : ' + port1);
});
const { sequelize } = require('./models')
// Sequelize가 초기화 될 때 DB에 필요한 테이블을 생성하는 함수
sequelize.sync()
.catch((error) => {
console.log(error);
});
/*
...
이하 필요한 코드
...
*/
6. 생성확인
6. service에서 CRUD해보기 (코드 일부만 갖고 왔다.)
//user_service.js 일부만
signup: async (signup_info) => { //가입
try {
//회원가입 전송
let result = await user.create(signup_info)
.catch(err => {
console.log(err);
return false;
});
if (result) {
return result.idx;
}//오류가 있는경우
} catch (error) {
console.log(error);
}
},
login: async (uesr_id, password) => { //로그인
//user_id로 정보찾기
try {
let result = await user.findOne({
attributes: ['idx', 'id', 'name', 'password', 'salt', 'user_photo', 'deletedAt'],
where: {
id: uesr_id
}
})
.catch(error => {
console.log(error);
});
//결과가 있으면
if (!result) { return false; } //없는 id
if (result) {
const user = result.dataValues;
if (user.deletedAt) { return ({ message: 'resign_user' }); } //탈퇴한 id : 탈퇴후 3개월 동안 같은 id 생성 불가
//비밀번호 비교
const db_password = user.password;
let hash_password = crypto.createHash("sha512").update(password + user.salt).digest("hex");
if (db_password === hash_password) {
return user;
} //세션에 유저정보를 저장하기 위함
if (db_password !== hash_password) { return ({ message: 'login_fail' }); } //비밀번호 틀림
}
} catch (error) {
console.log(error);
}
},
delete_user: async (user_idx) => { //탈퇴
try {
let result = await user.destroy({
}, {
where: {
idx: user_idx
}
}).catch(error => {
console.log(error);
});
return result;
} catch (error) {
console.log(error);
}
},
+ 그동한 발생했던 에러들
1. Dialect needs to be explicitly supplied as of v4.0.0
해결 1) 환경변수 재설정하기 set NODE_ENV=production 아니면 development
2. Cannot add foreign key constraint 혹은 ER_FK_NO_INDEX_PARENT
해결 1) 다른 테이블과의 fk가 어떻게 설정되어있는지 점검해보기
(필자는 mysql과 연결해서 쿼리문으로 데이터를 주고 받았었다. 시퀄라이즈 적용을 하기 위해 기존 post/user테이블을 삭제했는데 이둘과 FK로 연결된 다른 테이블(comment) 때문에 새로운 테이블 생성이 되지 않았었음)
'코딩 > expressJs' 카테고리의 다른 글
JWT 사용 정리 (0) | 2022.05.03 |
---|---|
express) Cookie와 Session쓰기 (0) | 2022.04.16 |
Nginx에서 reverse proxy 설정중 문제(해결중) (0) | 2022.03.20 |
expressjs의 mergeParams 사용해보기(매우 간단) (0) | 2022.02.03 |
nodejs express 로 아~주 기본적인 라우팅 설정 해보기(with Mysql) (0) | 2021.12.23 |