[ORM] Node.js에서 ORM 사용하기
Node.js에서 지원하는 ORM의 종류와 차이점 찾아보기
  • JavaScript

ORM(Object Relational Mapping) 이란?

ORM(Object Relational Model)은 사물을 추상화시켜 이해하려는 OOP적 사고방식과 DataModel을 정형화하여 관리하려는 RDB 사이를 연결할 계층의 역할로 제시된 패러다임으로 RDB의 모델을 OOP에 Entity 형태로 투영시키는 방식을 사용한다.

image

즉, Object와 Database간에 연결 역할을 해주는녀석이 ORM이다.


1. ORM의 등장배경

ORM을 사용하지 않을 경우 개발자가 개발을 위하여 Database에 접근하기 위해서는 SQL Query문을 직접 만들었다.

  • SQL문법을 알고 있어야하는 문제 (쿼리문 작성시간이 오래걸려 개발이 지체되는 문제가 발생)
  • 개발 코드와 Database가 서로 종속된다.

위와같은 문제점들이 생겨나기 시작했다.
이러한 문제점을 해결하기 위해 ORM이 등장하였고 ORM이 등장함으로서

  • SQL Query 문법에서 비교적 자유로워졌으며
  • 개발 코드와 Database를 분리함으로써 객체지향의 의도에 부합하게 되었다.

2. ORM사용의 장점과 단점

장점

  1. 개발의 생산성 향상
  • 선언문, 할당, 종료 등과같은 부수적인 코드가 사라짐으로써 개발의 생산성 향상.
  1. 명확한 쿼리 (버그와 실수 감소)
  • 코드그 간결하고 직관이기 때문에 가독성을 높여준다.
  1. DB 의존성 감소
  • 대부분 ORM 솔루션이 특정 Database에 종속적이지 않다.
    개발자는 Database에 상관없이 Object에만 집중할 수 있다.

단점

  1. 튜닝의 어려움
  • 미세한 수정 및 디버그하기가 상대적으로 어렵다
  1. 복잡한 쿼리작성의 문제
  • ORM이 지정해 놓은 명령만 내릴 수 있다
  1. Raw쿼리에 비해 느린 실행속도
  • DB에 직접 명령을 내리지 않고 한단계 거쳐가기 때문에

3. Raw SQL vs TypeORM vs Sequelize.js vs Knex

문법의 비교

// 1. SQL
const query = "SELECT * FROM post WHERE authorId = 12 AND status = 'active'";

// Knex
knex("post").select()
 .where({ authorId: 12, status: 'active'});

// Sequelize
models.Post.findAll({
    where: { authorId: 12, status: 'active' }
})

// TypeORM
connection.getRepository(Post).find({ where: { authorId: 12, status: 'active' } })
// 2. SQL
const query = "select * 
               from category_page 
               where category_id = 5
                 and (show_at is null or show_at >= now()) 
                 and (hide_at is null or hide_at <= now())
               order by updated_at desc 
               limit 1";
             
// Knex
knex("category_page")
      .where({ category_id: 5 })
      .where(b => b.whereNull('show_at').orWhere('show_at', '>=', moment(now).toDate()))
      .where(b => b.whereNull('hide_at').orWhere('hide_at', '<=', moment(now).toDate()))
      .orderBy('updated_at', 'desc')
      .first()

// Sequelize
models.CategoryPage.findOne({
    where: {
        category_id: 5,
        show_at: {
            [Op.or]: [
                { [Op.eq]: null },
                { [Op.gte]: now }
            ]
        },
        hide_at: {
            [Op.or]: [
                { [Op.eq]: null },
                { [Op.lte]: now }
            ]
        }
    },
    order: [['updated_at', 'DESC']]
})
// 참고 EQ("="), GTE(">="), GT(">"), LT("<"), LTE("<=");

// TypeORM
connection.getRepository(CategoryPage)
    .createQueryBuilder()
    .where("category_id = :categoryId", { categoryId: 5 })
    .andWhere("(show_at is null or show_at >= now())" )
    .andWhere("(hide_at is null or hide_at <= now())" )
    .orderBy("updated_at", "DESC")
    .limit(1)
    .getMany()

함수 실행속도 비교 (10번 실행한 결과의 평균 수치)

- raw typeORM Sequelize.js Knex.js
Query 1 0.8 2.19 8.42 3.86
Query 2 1.51 3.58 4.02 1.59
Query 3 1.39 3.92 9.13 2.13

— Query 1 : 단순 select 쿼리
— Query 2 : 단순 select 쿼리
— Query 3 : 단순 구조의 table 2개 join 쿼리

  • 단위 : (ms)
  • 실행 Server의 성능에 따라 결과는 달라질 수 있음

Github

- typeORM Sequelize.js Knex.js
Stars (git) 12,541 18,379 9,409
Language TypeScript TypeScript
(TS >= 3.1)
JavaScript
Google (English) ++ +++ ++
Google (Korean) ++ +++ ++

(NPM trends 로 확인하는 비교자료)

Support Databases

  • TypeORM : MySQL / MariaDB / Postgres / CockroachDB / SQLite / Microsoft SQL Server / Oracle / sql.js / MongoDB NoSQL
  • Sequelize : Postgres, MySQL, MariaDB, SQLite and Microsoft SQL Server.
  • Knex : PostgreSQL, MySQL and SQLite3

4. 그래서 어떤 것을 사용할 것인가?

후보 1
TypeORM, Sequelize(only TS >= 3.1 is supported.)

  • 장점 : TypeScript를 지원, 생산성, 신뢰성을 만족
  • 단점 : 실행속도, 튜닝의 어려움, 복잡한 쿼리작성 등의 단점(ORM의 단점)을 가지고 있으나, 이정도로 복잡하게 사용할 것인가? 고민

TypeORM, Sequelize의 차이점

  • Sequelize에 비해 상대적으로 속도가 빠른 TypeORM
  • TypeORM는 코드작성이 raw쿼리에 좀 더 가까운 모습

후보 2
인생은 날 쿼리. node-mysql/node-mysql2 only!

  • 장점 : 튜닝, 복잡한 쿼리작성의 문제, ORM에 비해 상대적으로 빠른 실행속도 모두를 만족!
  • 단점 : 생산성, 신뢰성 은 다소 떨어지는 단점

참고사이트