NestJS 09 | TypeOrm Transaction

임종성·2021년 9월 13일
4

NestJS

목록 보기
9/13
post-thumbnail

TypeORM을 활용한 API 구현에 이어서 이번엔 NestJS에서 TypeOrm을 활용한 Transaction에 대해 알아보겠습니다.

Transaction

Database Transaction은 DB에 대해 DB Management System에서 수행되는 작업 단위를 상징하며, 다른 Transaction과 독립적으로 일관되고 신뢰할 수 있는 방식으로 처리됩니다.

데이터베이스에서의 Transaction 처리는 Buisness Logic상 굉장히 중요한 기능입니다. 예를 들어 서로 다른 트랜잭션들을 처리하는 도중 하나의 단위 트랜잭션에서 에러가 발생한다면 이전에 성공 했던 트랜잭션들을 다시 rollback해야 데이터의 Consistency가 깨지지 않습니다. DB의 Transaction Flow는 간단하게 보면 다음과 같습니다.

1. 서로 다른 Transaction을 부분적으로 처리합니다.
2. 모든 Transaction이 정상적으로 완료되면 Commit 합니다.
3. 만약 Transaction중 하나라도 비정상적으로 처리되면 rollback을 수행합니다.

TypeOrm Transaction Strategies

TypeOrm의 Transaction을 처리하기 위한 다양한 전략이 존재합니다. 간단하게 @Transactional 데코레이터를 사용하여 해당 Method 위에서 간편하게 처리할 수도 있고, Callback Style로 처리할 수도 있습니다.

하지만 NestJS가 강력하게 추천하고 권고하는 방식은 바로 QueryRunner를 통해 Transaction을 수행하는 것입니다. QueryRunner를 사용하면 Transaction의 Commit과 Rollback을 수동으로 제어할 수 있습니다. QueryRunner를 활용하여 제가 구현한 regOrder API에 Transaction을 적용해 봅시다.

regOrder API

regOrder API는 Order를 추가하는 기능으로, 요청받은 Data로 Order Instance를 생성하고 Foregin Key로 연결되어 있는 Order Size 객체들을 생성합니다.

regOrder API의 기본 로직은 다음과 같습니다.

  1. Order Table을 생성하기 위해 필요한 Data로 먼저 Order Data를 DB에 저장합니다.
  2. 새롭게 생성된 Order 객체의 id와, Order하는 제품의 size별 주문수량을 OrderSize Table에 저장합니다.

여기서 만약, Order Instance를 생성한 후 size별 수량을 OrderSize Table에 생성하고 저장하는 과정에서 오류가 발생한다면, 이전에 성공했던 Transaction, 즉 Order Instance를 DB에 Commit하는 Transaction이 rollback 되어야 합니다.

따라서 이 일련의 두 과정을 QueryRunner를 활용해서 수동으로 Commit과 Rollback을 제어해 Transaction을 처리해 봅시다.

Dependency Injection

QueryRunner를 통해 Transaction을 처리하기 위해서 먼저 Connection 객체를 Order Service에 의존성 주입을 시켜야합니다.

Repository는 @InjectRepository 데로레이터로 의존성 주입을 하지만, Connection 객체는 이미 TypeOrm Module을 import한 것만으로도 의존성을 가져올 수 있습니다. 이 의존성을 토대로 createQueryRunner() 함수를 통해 Transaction Manager를 수행할 수 있습니다.

createQueryRunner and startTransaction

createQueryRunner함수로 queryRunner를 선언하고, Transaction의 시작을 선언해줍니다. Commit, Rollback을 수동으로 제어할 수 있듯이 Transaction의 시작과 끝 또한 제어할 수 있습니다.

commitTransaction and rollbackTransaction

Transaction이 처리되는 부분을 try & catch로 감싸주고, Transaction을 처리하는 save method는 repository가 아니라 queryRunner.manager로 대체해 줍니다.

Error 없이 모든 Transaction이 완료되면 commitTransactioin을 호출하고, 만약 Transaction에 이상이 생기면 rollbackTransaction을 호출해 모든 Transaction을 rollback 합니다. 그 후 release함수를 호출해 Transaction을 종료하고 `isSuccess를 반환합니다.

이렇게 QueryRunner를 활용하면 Transaction 수행을 원하는 로직에 대해 수동으로 Commit과 Rollback을 제어해 쉽게 처리할 수 있습니다. 다음에는 NestJS의 핵심인 Jest 기반의 Unit Test에 대해 다뤄보겠습니다.

profile
어디를 가든 마음을 다해 가자

0개의 댓글