TypeORM vs Prisma

본 글은 기존 velog에서 이전된 글입니다. (https://velog.io/@jinu0137/TypeORM-vs-Prisma)


1. ORM (Object Relation Mapping: 객체 관계 매핑)

1.1. ORM이란

  • 객체와 관계형 데이터베이스의 데이터를 자동으로 매핑(연결)해주는 것을 의미
    • 객체 지향 프로그래밍은 클래스를 사용하고 관계형 데이터베이스는 테이블을 사용하는데, 객체 모델과 관계형 모델 간에 불일치가 존재하게 됨
    • ORM을 통해 객체 간의 관계를 바탕으로 SQL을 자동으로 생성하여 불일치를 해결함
  • 객체를 통해 간접적으로 데이터베이스의 객체를 다룸
    • DB <= ORM(Mapping) => Object 필드

1.2. ORM을 사용하는 이유

  • 객체 지향적인 코드로 인해 더 직관적이고 비즈니스 로직에 집중할 수 있게 해줌
  • 재사용 및 유지보수의 편리성 증가
  • DBMS에 대한 종속성이 줄어듦

ORM 정리


2. TypeORM

2.1. TypeORM이란

  • Node.js 등과 같은 플랫폼에서 JavaScript, TypeScript와 함께 사용할 수 있는 ORM

2.2. TypeORM의 장점

  • 타 ORM과 달리 액티브 레코드 패턴과 데이터 매퍼 패턴을 모두 지원
  • 다양한 데이터 베이스를 지원 (MariaDB,NOSQL 등)

3. Prisma

3.1. Prisma란

3.2. Prisma의 장점

  • Prisma Studio라는 DB 접근 GUI를 제공함
  • GraphQL의 장점
    • HTTP 요청 횟수를 줄일 수 있음
    • HTTP 응답 사이즈를 줄일 수 있음
    • API의 request/response에 비교적 덜 의존할 수 있음

참고1, 참고2


4. 고려사항

4.1. 속도

  • Fluent API를 통해 Join을 할 경우 여러 쿼리로 분리되서 호출된다고 함
    • ex) member 테이블과 Team 테이블을 Join할 경우 총 2번의 질의가 실행됨
  • 아래 출처에서 10000개의 데이터로 테스트를 진행한 것을 참고하였음
    • Prisma의 경우 180-240ms, TypeORM의 경우 90-120ms가 걸렸음
    • 출처

4.2. 과도한 러닝커브 우려

  • 제공하는 기능이 너무 많음
    • Prisma의 경우 확실하게 Prisma Studio와 같이 편리한 기능을 제공해주지만 그만큼 러닝커브가 증가한다고 생각하였음
    • ex) 별도의 Schema 정의어 존재 ⇒ Schema 정의어 학습
  • 추가적으로 GraphQL 학습이 필요함
    • Prisma를 사용하기 위해선 GraphQL 역시 학습해야 한다는 부담감이 있었음
  • 우리 팀원 중 Prisma와 GraphQL을 사용해본 팀원이 없었음
    • TypeORM은 내가 지난 프로젝트에서 사용해본 경험이 있었음

4.3. 부가적인 이유

  • 화이트보드의 객체(드로잉, 포스트잇, 도형 등)를 어떻게 저장할 것인지 확정되지 않았음
    • GraphQL을 사용하게 되면, File 전송과 같이 Text로는 처리하기 힘들 경우 직접 구현해야함
  • GraphQL을 사용하면 고정된 요청과 응답만 필요할 때에는 query로 인해 요청의 크기가 Restful보다 커질 수 있음
  • Prisma의 경우 DateTime의 TimeZone 옵션이 존재하지 않음 (별도 구현해야함)
  • TypeORM의 경우, NestJS의 Default ORM이기 때문에 보다 많은 Reference들이 존재함

4.4. 결론 : TypeORM을 선택

  1. ‘부끄럼’이라는 프로젝트는 실시간 공유 편집 기능이 매우 중요하다. 그렇기 때문에 ‘반응 속도’가 중요한 고려사항 중 하나이다.
    • ERD 설계 상 Join이 빈번하게 일어날 것이고, 이를 고려한다면 Join을 테이블 하나 당 속도가 배로 늘어나는 Prisma 보다는 TypeORM이 우리 프로젝트에 적합할 것이라고 판단하였다.
  2. 6주 간 진행하는 프로젝트에서 Prisma와 GraphQL을 학습하며 구현하는 것은 부담이 될 수 있다.
    • NestJS와 ORM 두 가지 모두 학습해야 하는 팀원들도 있었는데, TypeORM에 비해 러닝커브가 높다고 판단되는 Prisma와 GraphQL을 추가로 학습하며 프로젝트를 진행하는 것은 부담이 된다고 판단하였다.
  3. 기타 부가적인 이유를 포함해서 고민한 결과 우리는 TypeORM을 사용하기로 결정하였다.

5. 성능 테스트

5.1. 계기

멘토님께 이 사안에 대해 말씀을 드렸고, 멘토님은 이 것을 주제로 기술 문서를 작성해보는 게 어떻냐는 의견을 주셨다. 그래서 내용을 보완할 겸, 주말에 직접 성능 테스트를 해보기로 마음을 먹었다.

5.2. 테스트 환경

  • 운영체제 : Windows 10
  • 데이터베이스 : MySQL 8.0.27 (로컬)
  • 서버 프레임워크 : NestJS + express
  • 자세한 테스트 모델은 링크를 참고하였다. (참고)

5.3. 테스트 방법

  • MySQL은 로컬 환경에서 진행한다.
  • Visual Studio Code를 통해 두 개의 서버를 동시에 실행한다.
  • PostMan을 통해 무작위로 20번 API를 호출하고 JavaScript의 console.time을 통해 쿼리가 실행되는 시간을 출력한다.
  • 그 후 실행 시간의 평균을 계산하여 비교한다.

5.4. 테스트 결과

 최고 시간평균 시간최소 시간
TypeORM175.65683.99662.263
Prisma142.241105.220690.935
차이값33.415-21.22528.672

5.5. 결론

  • 주의 : 본 테스트는 작성자의 컴퓨터 사양에 의존한다.
  • 두 ORM 모두 처음 API를 호출했을 때는 두 ORM 모두 실행 시간이 가장 오래 걸린다.
  • 최고 실행 시간은 TypeORM의 API가 가장 처음 실행된 시간이다.
  • 평균적으로 TypeORM이 약 20ms 정도 빠른 속도를 보여준다. (첫 실행 시간을 제외하면 더 큰 성능차가 남)

5.6. 후기

결론적으로 TypeORM이 조금 더 빠른 성능을 보여주는 것은 맞는 것 같다. 이전에 성능 테스트 게시글을 참고하여 ORM을 결정하였는데, 2년 전 게시글이다 보니 Prisma와 TypeORM 모두 업데이트가 많이 되어 성능의 차이가 클 것이라고 생각했다. 특히 Prisma의 경우에는 비교적 최신의 ORM이라 성능적으로 큰 향상을 기대했고, 혹시 TypeORM보다 더 좋은 성능을 보여주진 않을까 생각하였다.

다행히(?) TypeORM이 Join을 사용한 쿼리의 경우에 아직 더 좋은 성능을 자랑한다. 이러한 성능 테스트을 진행해본 건 거의 처음이였는데, 앞으로도 이런 기술 스택을 결정할 때 성능 테스트를 진행해보면 프로젝트를 진행할 때 도움이 많이 될 것 같다.