[express.js]02. ESM문법으로 sequelize 적용하기

김지엽·2023년 11월 13일
0
post-thumbnail
post-custom-banner

1. 개요

이전에 처음 express를 공부했을때는 commonJS로 작성했고, sequelize도 commonJS로 작성된 코드는 참고할게 많아서 문제가 없었다.

하지만 nestJS를 공부하고 난 후인 지금, 새로운 express 프로젝트에는 ESM을 적용했기 때문에 sequelize 코드 또한 새롭게 작성할 필요가 있다. 이번에는 ESM 환경에서 express 프로젝트에 sequelize를 적용시켜 볼려고한다.

2. ESM에서 Sequelize 사용하기

- sequelize 세팅

먼저, 필요한 라이브러리를 설치한다.

$ npm i sequelize mysql2
$ npm i -D sequelize-cli

sequelize-cli는 터미널에서 데이터베이스를 조작할 수 있게 도와주는 라이브러리이다.

프로젝트에 sequelize를 적용시킨다.

$ npx sequelize init

위 명령어를 실행하면 config, models, mirgration, seeders 총 4개의 폴더가 생성된다.

- sequelize 연결

이제 자신의 mysql 서버를 연결한다. mysql 서버에 대한 정보는 config폴더에 config.json을 수정한다.

{
  "development": {
    "username": "root",
    "password": "example_password",
    "database": "camp_project_04",
    "host": "example@host",
    "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"
  }
}

그리고 npx sequelize init를 통해 models 폴더에 index.js는 ESM 문법이 아닌 commonJS 문법으로 이루어져 있기 때문에 이를 수정해주어야 한다.

먼저 index.js 안의 내용을 전부 지운다. 그리고 다음과 같은 내용을 작성한다.

import Sequelize from 'sequelize';
import * as configEX from "../config/config.json" assert { type: 'json' };

// 환경변수에 따라 config를 설정
const env = process.env.NODE_ENV || 'development';
const config = configEX.default[env];
const db = {};

// db 객체에 sequelize 객체를 저장
const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;

export default db;

이제 app.js에서 실제로 데이터베이스가 연결되었는지 확인을 해준다.

...

// DB
const { sequelize } = db;
sequelize.sync({ force: false })
.then(() => {
	console.log("데이터베이스 연결 성공");
})
.catch(() => {
	console.log("데이터베이스 연결 실패");
});

...

const server = app.listen(app.get("port"), () => {
	console.log(app.get("port") + "번 포트에서 서버 실행");
});

sequelize의 sync 메서드는 단순히 데이터베이스 연결 확인을 위해 사용하는 함수가 아니다. 정확히는 sequelize에서 작성된 내용에 맞게 연결된 데이터베이스에 테이블을 생성 또는 변경하는 등의 동기화를 목적으로 하는 메서드이다.

서버를 실행해 다음과 같은 실행결과가 출력되면 성공이다.

- ESM에 맞게 model 파일 생성 및 작성하기

sequelize에서 우리가 작성할 테이블에 대한 정보를 두 위치에 적게되는데 migration과 model이다.

일반적으로 migration은 테이블의 생성및 변경에 사용되고, model은 데이터베이스의 해당 테이블로 연결할때 사용된다.

commonJS에서는 다음과 같은 명령어로 model 파일과 migration 파일을 생성한다.

$ npx sequelize model:generate --name 테이블이름 --attributes 컬럼:데이터형태, 컬럼:데이터형태

하지만 이 파일들을 commonJS 문법으로 작성되었기에 나는 그냥 처음부터 작성했다.

model폴더에 모델 파일을 생성한다.

모델 파일안에 테이블 정보를 입력한다.

import { Model, DataTypes } from "sequelize";

export default class User extends Model {
  	// 해당 모델의 정보를 초기화 하는 정적 메서드
	static init(sequelize) {
		return super.init({
			id: {
				type: DataTypes.INTEGER,
				allowNull: false,
				primaryKey: true,
				autoIncrement: true
			},
			name: {
				type: DataTypes.STRING(100),
				allowNull: false
			},
            sex: {
                type: DataTypes.STRING(10),
                allowNull: true
            },
			email: {
				type: DataTypes.STRING(100),
				allowNull: false,
				unique: true
			},
			password: {
				type: DataTypes.STRING(255),
				allowNull: false
			},
		}, {
         	// 테이블에 추가적인 설정
			sequelize,
			timestamps: true,
			underscored: false,
			modelName: "User",
			tableName: "users",
			paranoid: true,
			charset: "utf8",
			collate: "utf8_general_ci",
		});
	}
	
  	// 해당 모델의 관계를 정의하는 정적 메서드
	static associate(db) {
		db.User.hasMany(db.Product, { as: 'products', foreignKey: 'id', sourceKey: "id" });
	}
}
import { Model, DataTypes } from "sequelize";

export default class Product extends Model {
	static init(sequelize) {
		return super.init({
			id: {
				type: DataTypes.INTEGER,
				allowNull: false,
				primaryKey: true,
				autoIncrement: true
			},
			title: {
				type: DataTypes.STRING(100),
				allowNull: false
			},
            content: {
                type: DataTypes.STRING(255),
                allowNull: true
            },
			state: {
				type: DataTypes.STRING(20),
				allowNull: false,
                defaultValue: "FOR_SALE"
			},
			password: {
				type: DataTypes.STRING(255),
				allowNull: false
			},
		}, {
			sequelize,
			timestamps: true,
			underscored: false,
			modelName: "Product",
			tableName: "products",
			paranoid: true,
			charset: "utf8",
			collate: "utf8_general_ci",
		});
	}
	
	static associate(db) {
		db.Product.belongsTo(db.User, { foreignKey: 'id', targetKey: "id" });
	}
}

그리고 models 폴더에 index.js에 생성한 모델을 적용시켜야 한다.

import Sequelize from 'sequelize';
import * as configEX from "../config/config.json" assert { type: 'json' };
import User from "./users.model.js";
import Product from "./products.model.js";

const env = process.env.NODE_ENV || 'development';
const config = configEX.default[env];
const db = {};

const sequelize = new Sequelize(config.database, config.username, config.password, config);
db.sequelize = sequelize;
db.Sequelize = Sequelize;

db.User = User;
db.Product = Product;

User.init(sequelize);
Product.init(sequelize);

User.associate(db);
Product.associate(db);

export default db;

위와 같이 작성한 뒤에 만약 서버를 실행한다면 sequelize.sync 메서드 때문에 데이터베이스가 자동으로 동기화 되어서, 테이블이 생성될 것이다.

본인은 migration을 통해 테이블을 생성하는 것보다 위의 방식처럼 테이블을 생성하고 migration은 변경에 사용하는 것을 선호한다.

- migration 파일 생성하기

마이그레이션 파일은 다음 명령어를 통해 생성한다.

$ npx sequelize-cli migration:generate --name 파일이름 --models-path 모델파일경로

그러면 다음과 같은 파일이 생성된다.

'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
  async up (queryInterface, Sequelize) {
    /**
     * Add altering commands here.
     *
     * Example:
     * await queryInterface.createTable('users', { id: Sequelize.INTEGER });
     */
  },

  async down (queryInterface, Sequelize) {
    /**
     * Add reverting commands here.
     *
     * Example:
     * await queryInterface.dropTable('users');
     */
  }
};

migration 파일에서 up은 테이블의 변경하고 새로운 상태로 변경하는 역할(업데이트)을 하며, down은 up을 통한 변경사항을 롤백하는 역할을 한다.

이미 테이블 생성은 완료했고 지금 데이터베이스에 변경사항은 없으니 migration을 통해 테이블을 업데이트 하는 것은 추후에 다뤄볼 것이다.

그리고 migration 파일은 서버 실행에 필요한 것이 아닌 sequelize-cli를 통해 조작하므로 ESM 문법대로 수정할 필요가 없다.

참고

ESM문법으로 sequelize를 작성하는 블로그가 거의 안보여 참고할 블로그를 찾지 못하였다..

profile
욕심 많은 개발자
post-custom-banner

0개의 댓글