https://growth-coder.tistory.com/274
지난 포스팅에서 Express 기초에 대해 알아보고 mysql 데이터베이스와 연결하여 직접 SQL 쿼리문을 날려 데이터를 조작해보았다.
이번 포스팅에서는 sequelize 패키지를 사용하여 ORM으로 데이터베이스의 데이터에 접근해보려고 한다.
간단하게 Team 테이블과 1:N 관계를 가지고 있는 User 테이블을 사용하여 sequelize를 사용해보자.
패키지 설치
npm init으로 package.json 파일을 생성하자.
npm init
다음 패키지를 설치한다.
npm install express mysql2 nodemon sequelize sequelize-cli
이전 포스팅에서는 mysql 패키지를 사용했는데 sequelize에서 에러가 발생하여 mysql2로 변경하였다.
package.json에서 scripts.start와 type을 작성해준다.
{
"name": "sequel-commonjs",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start" : "nodemon index.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.19.2",
"mysql2": "^3.9.7",
"nodemon": "^3.1.0",
"sequelize": "^6.37.3",
"sequelize-cli": "^6.6.2"
},
"type" : "commonjs"
}
이전 포스팅에서는 ES Module을 사용했는데 sequelize에서 기본적으로 생성해주는 코드가 commonJS로 이루어져 있어서 commonJS로 진행하려고 한다.
위에서는 package.json에 "type": "commonjs"를 작성해줬지만 commonjs는 기본 값이라서 굳이 작성해주지 않아도 된다.
데이터베이스 세팅
우선 데이터베이스 설정을 위해 database 폴더를 만들고 그 안으로 이동한 후 npx sequelize init 명령어를 사용한다.
mkdir database
cd database
npx sequelize init
npx sequelize init 명령어를 사용하면 그 안에 config, migrations, models, seeders 폴더가 생긴다.
이 중 config 폴더 내부의 config.json에서 데이터베이스 설정을 변경할 수 있다.
config.json을 보면 아래와 같이 development, test, production 환경 별로 설정을 다르게 할 수 있다.
{
"development": {
"username": "root",
"password": null,
"database": "database_development",
"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"
}
}
development에서 mysql에 설정되어 있는 user 정보와 데이터베이스 정보를 입력하자.
sequelize 사용법을 익히는 것이 목적이니까 develpment에만 데이터베이스를 연결해서 테스트 해 볼 예정이다.
{
"development": {
"username": "root",
"password": "0000",
"database": "sequelize_development",
"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"
}
}
각자 로컬에 존재하는 데이터베이스 정보를 입력하면 된다.
직접 로컬 데이터베이스를 생성해도 되지만 sequelize-cli를 사용하면 쉽게 데이터베이스를 생성할 수 있다.
config/config.json에 원하는 데이터베이스 설정을 하고 아래 명령어를 입력하면 데이터베이스를 생성해준다.
npx sequelize db:create
이제 models/ 폴더 내부의 index.js를 수정해보자.
모델 세팅 (테이블 세팅)
우리는 ORM을 사용하여 자바스크립트에서 객체 형식으로 데이터를 다룰 예정이다.
먼저 models/index.js 파일을 다음과 같이 수정한다.
<models/index.js>
const Sequelize = require('sequelize');
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
module.exports = db;
이제 Team 모델을 만들어보자.
Model을 만드는 방법은 Model Definition과 Model Extending이 있다.
이 중 Model Extending을 사용해보자.
Sequelize.Model을 상속받아서 구현하면 된다.
<./models/Team.js>
const {Sequelize, DataTypes, Model} = require('sequelize')
module.exports = class Team extends Model{
static init(sequelize){
return super.init({
name: {
type: DataTypes.STRING,
allowNull: false
}
},
{
sequelize,
timestamps: true, // column에 자동으로 createdAt, updatedAt이 생성
modelName: 'Team', // 모델 이름
tableName: 'teams', // 데이터베이스 테이블 이름
paranoid: false, // true로 하면 데이터베이스에서 실제로 삭제하지 않고 deletedAt column을 사용해서 삭제
charset: 'utf8mb4', // 캐릭터 셋
collate: 'utf8mb4_general_ci' // 정렬 기준
})
}
}
첫 번째 객체엔 컬럼 설정 정보, 두 번째 객체엔 추가적인 설정 정보를 입력하면 된다.
init 메소드를 static으로 만들어서 models/index.js에서 이 init을 호출할 예정이다.
User도 만들어보자.
<./models/User.js>
const {Sequelize, DataTypes, Model} = require('sequelize')
module.exports = class User extends Model {
static init(sequelize){
return super.init({
name:{
type: DataTypes.STRING,
allowNull: false
},
age: {
type: DataTypes.INTEGER,
allowNull: false
}
},
{
sequelize,
timestamps: true, // column에 자동으로 createdAt, updatedAt이 생성
modelName: 'User', // 모델 이름
tableName: 'users', // 데이터베이스 테이블 이름
paranoid: false, // true로 하면 데이터베이스에서 실제로 삭제하지 않고 deletedAt column을 사용해서 삭제
charset: 'utf8mb4', // 캐릭터 셋
collate: 'utf8mb4_general_ci' // 정렬 기준
})
}
}
이제 models/index.js 파일을 수정할 차례이다.
<models/index.js>
// Sequelize 객체 가져오기
const Sequelize = require('sequelize');
// model 가져오기
const Team = require('./team')
const User = require('./user')
// config 가져오기
const env = process.env.NODE_ENV || 'development';
const config = require('../config/config')[env];
// db 설정
const db = {};
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.Team = Team
db.User = User
// association 설정
// Team과 User는 1:N 관계
Team.init(sequelize)
User.init(sequelize)
Team.hasMany(User)
User.belongsTo(Team)
module.exports = db;
모델들을 서로 1:N으로 연결시킨 모습을 볼 수 있다.
이렇게 모델들을 만들었으면 이 모델들과 매핑되는 테이블을 생성할 차례이다.
이 테이블은 직접 생성하는게 아니라 데이터베이스를 연결할 때 생성된다.
이제 index.js에서 데이터베이스를 연결하는 코드를 작성해보자.
const express = require('express')
const {sequelize, Team, User} = require('./database/models')
sequelize.sync({force: false})
.then(()=>{
console.log('데이터베이스 연결 성공')
})
.catch((err)=>{
console.log(err)
})
const app = express()
app.listen(3001, ()=>{
console.log("3001 포트 연결")
})
sequelize.sync를 실행하면 Model에 매핑되는 테이블들이 생성된다.
연관 관계
Team과 User는 1:N 매핑을 이루고 있고 데이터를 삽입할 때 이러한 연관 관계를 삽입하는 방법을 알아보자.
1. method 사용
async function init(){
const team = await Team.create({
name: "첫 번째 팀"
})
const user = await User.create({
"name" : "김철수",
"age" : 12
})
team.addUser(user)
}
Model의 add모델 메소드를 사용해서 연관 관계를 매핑할 수 있다.
2. foreign key 사용
async function init2(){
const team = await Team.create({
name: "첫 번째 팀"
})
const user = await User.create({
"TeamId": team.id,
"name" : "김철수",
"age" : 12
})
}
직접 foreign key를 넣어서 연관 관계를 매핑할 수 있다.
app.listen에서 서버가 실행될 때 위 함수를 사용해서 데이터를 넣어보자.
const express = require('express')
const {sequelize, Team, User} = require('./database/models')
sequelize.sync({force: false})
.then(()=>{
console.log('데이터베이스 연결 성공')
})
.catch((err)=>{
console.log(err)
})
const app = express()
app.listen(3001, ()=>{
console.log("3001 포트 연결")
init2()
})
async function init(){
const team = await Team.create({
name: "첫 번째 팀"
})
const user = await User.create({
"name" : "김철수",
"age" : 12
})
team.addUser(user)
}
async function init2(){
const team = await Team.create({
name: "첫 번째 팀"
})
const user = await User.create({
"TeamId": team.id,
"name" : "김철수",
"age" : 12
})
}
데이터베이스의 User 테이블에 추가된 User의 TeamId가 잘 매핑되었는지 확인해보자.
create 외의 다양한 쿼리들은 아래 공식 문서를 참고하면 쉽게 구현할 수 있다.
https://sequelize.org/docs/v6/core-concepts/model-querying-basics/
'공부 > express' 카테고리의 다른 글
[Express] passport 모듈을 통해 jwt 인증, 인가 구현 (1) | 2024.05.21 |
---|---|
[Express] passport 모듈을 통해 쿠키 세션 방식으로 로그인 구현 (0) | 2024.05.18 |
[Express] API 작성법 (라우터, 컨트롤러 분리) (0) | 2024.05.16 |
[Express] mongoose 사용법 (mongoDB ORM) (0) | 2024.05.14 |
[express] express 웹 서버 기초 (0) | 2024.05.08 |
댓글