Sequelize

Sequelize는 Node.js를 위한 현대적이고 강력한 Promise 기반 ORM(Object-Relational Mapping) 라이브러리.
관계형 데이터베이스와 상호작용하는 복잡한 작업을 단순화하고 추상화해준다.

ORM은 객체지향 프로그래밍 언어와 관계형 데이터베이스 사이의 번역기 역할을 한다.
복잡한 SQL 쿼리를 직접 작성하지 않고도 데이터베이스를 쉽게 조작할 수 있게 해준다.

Sequelize의 장점

  • 데이터베이스 추상화
  • 강력한 관계 설정
  • 데이터 검증
  • 마이그레이션 지원
  • 다양한 데이터베이스 호환성

주의사항

  • 대규모 애플리케이션에서는 성능 최적화 필요
  • ORM의 복잡성을 이해해야 함
  • 직접 SQL 쿼리도 학습 권장

Sequelize의 주요 특징

  1. 다양한 데이터베이스 지원: MySQL, PostgreSQL, SQLite, MariaDB, MSSQL 등 여러 관계형 데이터베이스를 지원한다.
  2. 객체 지향적 접근: JavaScript 객체를 통해 데이터베이스 테이블을 표현하고 조작할 수 있다.
  3. 스키마 정의: 모델을 통해 데이터베이스 스키마를 정의하고 관리할 수 있다.
  4. 관계 설정: 모델 간의 관계(1:1, 1:N, N:M)를 쉽게 정의하고 관리할 수 있다.
  5. 쿼리 빌딩: SQL 쿼리를 직접 작성하지 않고도 JavaScript 메서드를 통해 데이터베이스 작업을 수행할 수 있다.

기본 설정 및 연결

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
const { Sequelize, DataTypes } = require('sequelize');

// 데이터베이스 연결
const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql', // 사용하는 데이터베이스 종류
  logging: false    // SQL 로그 비활성화
});

// 연결 테스트
try {
  await sequelize.authenticate();
  console.log('데이터베이스 연결 성공!');
} catch (error) {
  console.error('연결 실패:', error);
}

모델 정의와 관계

기본 모델 생성

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
const User = sequelize.define('User', {
  // 속성 정의
  firstName: {
    type: DataTypes.STRING,
    allowNull: false
  },
  lastName: {
    type: DataTypes.STRING
  },
  email: {
    type: DataTypes.STRING,
    unique: true,
    validate: {
      isEmail: true
    }
  },
  age: {
    type: DataTypes.INTEGER,
    validate: {
      min: 18,
      max: 100
    }
  }
}, {
  // 모델 옵션
  timestamps: true, // createdAt, updatedAt 자동 생성
});

모델 간 관계 설정

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// 1:N 관계 (One-to-Many)
const Post = sequelize.define('Post', {
  title: DataTypes.STRING,
  content: DataTypes.TEXT
});

// 사용자와 포스트 관계 정의
User.hasMany(Post);
Post.belongsTo(User);

// N:M 관계 (Many-to-Many)
const Project = sequelize.define('Project', {
  name: DataTypes.STRING
});

User.belongsToMany(Project, { through: 'UserProjects' });
Project.belongsToMany(User, { through: 'UserProjects' });

CRUD 작업

데이터 생성

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// 단일 레코드 생성
const newUser = await User.create({
  firstName: 'John',
  lastName: 'Doe',
  email: 'john@example.com'
});

// 대량 생성
await User.bulkCreate([
  { firstName: 'Alice', lastName: 'Smith' },
  { firstName: 'Bob', lastName: 'Johnson' }
]);

데이터 조회

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
// 모든 사용자 조회
const users = await User.findAll();

// 조건부 조회
const youngUsers = await User.findAll({
  where: {
    age: {
      [Op.lt]: 30  // 30세 미만
    }
  },
  include: [Post]  // 연관된 포스트 함께 조회
});

// 단일 사용자 조회
const user = await User.findByPk(1);

데이터 업데이트

1
2
3
4
5
// 단일 레코드 업데이트
await User.update(
  { lastName: 'NewLastName' },
  { where: { id: 1 } }
);

데이터 삭제

1
2
3
4
// 단일 레코드 삭제
await User.destroy({
  where: { id: 1 }
});

트랜잭션 처리

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
const result = await sequelize.transaction(async (t) => {
  const user = await User.create({
    firstName: 'Transactional',
    lastName: 'User'
  }, { transaction: t });

  await user.createPost({
    title: '첫 번째 포스트',
    content: '트랜잭션 내 생성'
  }, { transaction: t });

  return user;
});

마이그레이션

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
// 마이그레이션 예시
module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('Users', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      firstName: {
        type: Sequelize.STRING
      }
    });
  },
  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable('Users');
  }
};

학습 로드맵

  1. JavaScript 기본 문법 숙달
  2. Node.js 기초 학습
  3. SQL 기본 개념 이해
  4. Sequelize 기본 CRUD 작업 연습
  5. 관계 모델링 및 고급 쿼리 학습

참고 및 출처

Sequelize | Feature-rich ORM for modern TypeScript & JavaScript