백엔드/Node.js
[Node.js] Sequlize 마이그레이션 방법
순코딩
2024. 11. 1. 17:32
참고자료
들어가며
해당 게시물은 아래링크와 관련성이 높은 글이며 프로젝트 세팅이 완료되어있음을 가정합니다.
만약 프로젝트 세팅이 되어 있지 않다면 아래 링크를 참고해주세요.
모델 정의
// models/Product.js
"use strict";
// Sequelize에서 Model 클래스를 가져옵니다.
const { Model } = require("sequelize");
module.exports = (sequelize, DataTypes) => {
// Product 모델 정의
class Product extends Model {
// 모델 간의 관계를 정의하는 associate 메서드
static associate(models) {
// Product는 Nutritional 모델과 1:1 관계를 가집니다.
Product.hasOne(models.Nutritional, {
foreignKey: "id", // Nutritional 모델에서 참조하는 외래 키
as: "nutritional", // 관계의 별칭
});
}
}
// Product 모델의 속성(컬럼) 정의
Product.init(
{
// id 컬럼: 기본 키, 자동 증가 설정
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
// name 컬럼: 제품 이름을 저장하며 NULL 값을 허용하지 않음
name: {
type: DataTypes.STRING,
allowNull: false,
},
// link 컬럼: 제품 링크를 저장하며 NULL 값을 허용하지 않음
link: {
type: DataTypes.STRING,
allowNull: false,
},
// src 컬럼: 이미지 경로를 저장하며 NULL 값을 허용하지 않음
src: {
type: DataTypes.STRING,
allowNull: false,
},
// major_category 컬럼: 대분류 카테고리 이름, 최대 길이 100, NULL 값 허용 안 함
major_category: {
type: DataTypes.STRING(100),
allowNull: false,
},
// middle_category 컬럼: 중분류 카테고리 이름, 최대 길이 100, NULL 값 허용 안 함
middle_category: {
type: DataTypes.STRING(100),
allowNull: false,
},
},
{
// Sequelize 인스턴스를 연결하여 Product 모델 초기화
sequelize,
modelName: "Product", // 모델 이름
tableName: "products", // 실제 데이터베이스 테이블 이름
timestamps: true, // createdAt, updatedAt 타임스탬프 컬럼 자동 생성
charset: 'utf8mb4', // 이모지 지원을 위한 UTF-8 4바이트 설정
collate: 'utf8mb4_unicode_ci' // 유니코드 정렬 및 대소문자 구분 없음
}
);
return Product; // Product 모델 반환
};
필자의 Product.js 모델은 위와 같이 작성되어 있습니다.
아래 과정을 통해 해당 모델을 DB로 마이그레이션할 것입니다.
마이그레이션
정의
마이그레이션(Migration)은 데이터베이스의 구조(스키마)를 변경하고 관리하는 작업을 의미합니다.
마이그레이션을 사용하면 테이블과 컬럼의 생성, 삭제, 수정 등의 변경 사항을 코드로 관리할 수 있으며, 이러한 변경 내역을 기록하고 추적할 수 있습니다.
마이그레이션은 버전 관리가 가능하여, 데이터베이스 구조 변경을 되돌리거나 특정 시점으로 복구할 수 있습니다.
마이그레이션 파일은 Sequelize에서 데이터베이스의 구조적 변경을 정의하고 관리하는 파일입니다.
데이터베이스 스키마(테이블, 컬럼, 인덱스, 제약 조건 등)의 변경 작업을 SQL 대신 자바스크립트 코드로 작성하여 쉽게 적용하거나 롤백할 수 있습니다.
모델(Model)은 Sequelize에서 데이터베이스 테이블 구조를 자바스크립트 객체로 표현한 것입니다.
모델을 통해 데이터베이스의 테이블 구조와 제약 조건을 정의하고, 이를 자바스크립트 객체로 다루어 데이터베이스 작업을 수행할 수 있습니다.
각 모델은 데이터베이스의 특정 테이블과 매핑되며, 테이블의 컬럼을 속성으로, 테이블 간의 관계를 객체 간의 관계로 정의합니다.
구분 | 마이그레이션(Migration) 파일 | 모델(Model) 파일 |
역할 | 데이터베이스의 스키마를 변경하고, 테이블 구조를 정의하며, 테이블 및 컬럼의 생성과 수정을 관리함 | 데이터베이스의 테이블과 매핑되는 자바스크립트 객체로, 데이터를 다루기 위한 논리적 구조와 관계를 정의함 |
주요 작업 | 테이블 생성, 삭제, 컬럼 추가, 수정, 삭제, 인덱스 및 제약 조건 설정 | 데이터베이스 테이블과의 매핑을 통해 객체 지향적으로 데이터를 다루며, 테이블 간의 관계를 정의함 |
연관된 작업 | up 함수와 down 함수로 스키마 변경 작업을 정의하고, 데이터베이스 구조 변경 시 이를 반영함 | 모델 정의를 통해 생성된 객체를 통해 데이터 CRUD 작업과, 다른 모델과의 관계 설정에 사용됨 |
데이터베이스 연동 | 마이그레이션 파일은 Sequelize가 데이터베이스 구조를 변경할 때만 사용됨 | 모델 파일은 데이터베이스와 상시 연동되어 데이터를 객체 지향 방식으로 관리함 |
마이그레이션 파일 생성
명령어
# migration/ 폴더에 {타임스탬프}-change-products 라는 이름의 마이그레이션 파일이 생성됩니다.
$ npx sequelize-cli migration:generate --name change-products
위 명령어를 사용하여 마이그레이션 파일을 생성합니다.
마이그레이션 파일 살펴보기
초기 코드
'use strict';
module.exports = {
async up (queryInterface, Sequelize) {
// ...
},
async down (queryInterface, Sequelize) {
// ...
}
};
migration/ 폴더로 들어가 생성된 마이그레이션 파일을 확인하면 위처럼 작성되어 있습니다.
코드 해석
"use strict";
module.exports = {
up: async (queryInterface, Sequelize) => {
// 데이터베이스에 적용할 변경 사항 작성
},
down: async (queryInterface, Sequelize) => {
// 변경 사항을 되돌리는 코드를 작성
}
};
up 함수
마이그레이션을 실행할 때 데이터베이스에 적용할 변경 사항을 정의합니다.
예를 들어, 새로운 테이블 생성, 컬럼 추가 등을 작성합니다.
down 함수
up 함수에서 적용한 변경 사항을 롤백하여 되돌리는 코드를 작성합니다.
예를 들어, 생성한 테이블 삭제, 추가한 컬럼 제거 등을 수행합니다.
queryInterface 인수
queryInterface는 데이터베이스와 상호작용하는 다양한 메서드를 제공합니다.
이 객체를 통해 테이블 생성, 삭제, 컬럼 추가, 제약 조건 추가 등 데이터베이스 스키마를 변경하는 작업을 수행할 수 있습니다.
Sequelize 인수
Sequelize는 Sequelize 라이브러리의 전체 객체로, 데이터 타입 및 기타 설정을 제공합니다.
이를 통해 컬럼의 데이터 타입을 지정하고 기본값이나 제약 조건 설정을 추가할 수 있습니다.
예시 코드
// migrations/YYYYMMDDHHMMSS-create-products.js
"use strict";
module.exports = {
// `up` 함수: 마이그레이션 실행 시 호출되어 테이블을 생성하는 역할을 합니다.
up: async (queryInterface, Sequelize) => {
// 인수 queryInterface 객체의 `createTable` 메서드를 통해 `products` 테이블 생성
await queryInterface.createTable(
// 생성할 테이블 이름
"products",
// 테이블의 컬럼 정의
{
// `id` 컬럼: 기본 키, 자동 증가
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true,
allowNull: false,
},
// `name` 컬럼: 제품 이름을 저장하는 필드, NULL 허용 안 함
name: {
type: Sequelize.STRING,
allowNull: false,
},
// `link` 컬럼: 제품 링크를 저장하는 필드, NULL 허용 안 함
link: {
type: Sequelize.STRING,
allowNull: false,
},
// `src` 컬럼: 제품 이미지 경로를 저장하는 필드, NULL 허용 안 함
src: {
type: Sequelize.STRING,
allowNull: false,
},
// `major_category` 컬럼: 대분류 카테고리를 저장, 최대 길이 100자, NULL 허용 안 함
major_category: {
type: Sequelize.STRING(100),
allowNull: false,
},
// `middle_category` 컬럼: 중분류 카테고리를 저장, 최대 길이 100자, NULL 허용 안 함
middle_category: {
type: Sequelize.STRING(100),
allowNull: false,
},
// `createdAt` 컬럼: 레코드 생성 시간을 자동 기록
createdAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.NOW,
},
// `updatedAt` 컬럼: 레코드 수정 시간을 자동 기록
updatedAt: {
type: Sequelize.DATE,
allowNull: false,
defaultValue: Sequelize.NOW,
},
},
// 테이블 옵션 설정
{
charset: "utf8mb4", // UTF-8 4바이트 문자 지원, 이모지 포함 가능
collate: "utf8mb4_unicode_ci", // 유니코드 정렬, 대소문자 구분 없는 정렬 방식
}
);
},
// `down` 함수: 마이그레이션 롤백 시 호출되어 `products` 테이블을 삭제합니다.
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable("products");
},
};
마이그레이션 파일의 up 함수는 마이그레이션 실행 시 데이터베이스에 적용할 작업을 정의하는 함수입니다.
up 함수 내에는 보통 테이블 생성, 컬럼 추가, 제약 조건 설정 등의 작업이 포함되며, 이 작업들은 queryInterface 객체의 메서드를 통해 이루어집니다.
queryInterface는 Sequelize에서 데이터베이스와 상호작용할 수 있는 고수준 API 객체로, 다양한 데이터베이스 조작 메서드를 포함하고 있습니다.
이 중 createTable 메서드는 데이터베이스에 테이블을 생성하는 메서드로, 테이블의 이름, 컬럼 속성, 옵션을 인수로 받아 테이블을 정의합니다.
await queryInterface.createTable(tableName, attributes, options);
인수 설명
tableName (string) :
생성할 테이블의 이름을 지정하는 문자열입니다.
예: "products", "users", "orders"
attributes (object) :
테이블의 컬럼과 각 컬럼의 속성을 정의하는 객체입니다.
각 컬럼 속성은 Sequelize의 DataTypes 객체를 사용하여 정의할 수 있습니다.
이 객체에서 키는 컬럼 이름을 나타내며, 값은 해당 컬럼의 속성 정의입니다.
options (object, 선택 사항) :
테이블 전체에 적용할 추가 설정을 정의하는 객체입니다.
옵션 설정은 선택 사항이며, 테이블의 기본적인 특성을 설정할 수 있습니다.
마이그레이션 실행
$ npx sequelize-cli db:migrate
위 명령어는 migrations 폴더에 있는 마이그레이션 파일의 up 함수를 순차적으로 실행하여 데이터베이스 스키마를 변경합니다.
이 때, 새로 추가된 마이그레이션 파일만 실행되며, 이미 실행된 파일은 다시 실행되지 않습니다.
마이그레이션 롤백
$ npx sequelize-cli db:migrate:undo
가장 최근에 실행된 마이그레이션을 롤백
$ npx sequelize-cli db:migrate:undo:all
모든 마이그레이션 롤백
$ npx sequelize-cli db:migrate --name {마이그레이션 파일명}
ex) $ npx sequelize-cli db:migrate --name 20241101022741-create-product.js
특정 마이그레이션 파일 실행 또는 롤백