민프

[Nest.js] NestJS에서 TypeORM, QueryRunner와 트랜잭션(Transaction) : 실무에서 반드시 알아야 할 트랜잭션 제어 기법, 트랜잭션(Transaction)이란? 본문

Backend/[Nest.js]

[Nest.js] NestJS에서 TypeORM, QueryRunner와 트랜잭션(Transaction) : 실무에서 반드시 알아야 할 트랜잭션 제어 기법, 트랜잭션(Transaction)이란?

민프야 2025. 5. 30. 20:00

https://ko.wikipedia.org/wiki/NestJS

왜 트랜잭션 제어가 필요할까?

NestJS로 서비스를 개발하다 보면, 여러 테이블에 걸친 데이터 변경을 수행해야 할 때가 많습니다. 
이런 경우 트랜잭션(Transaction)은 데이터의 정합성과 무결성을 지키기 위한 필수 도구입니다.


NestJS는 `TypeORM`을 기반으로 `queryRunner`를 통해 트랜잭션을 정교하게 제어할 수 있게 해줍니다.

이 글에서는 `queryRunner`의 사용법과 함께, 실무에서 겪을 수 있는 문제와 최적의 활용 전략까지 자세히 다뤄보겠습니다.


트랜잭션이 필요한 순간들

트랜잭션이 필요한 순간들을 알아보기 전에

간단하게 트랜잭션이란 무엇인지 알아보겠습니다.

트랜잭션(Transaction)은 데이터베이스에서 하나의 작업 단위를 의미하는 개념입니다. 여러 개의 데이터 처리 작업이 하나의 트랜잭션 안에 포함되면, 이 작업들은 모두 성공하거나 모두 실패해야만 합니다.

예를 들어, "주문 → 결제 → 재고 차감"이라는 세 단계가 있을 때, 결제는 되었지만 재고 차감이 실패하면 문제가 생기겠죠? 이럴 때 트랜잭션을 사용하면, 중간에 문제가 생기면 모든 작업을 이전 상태로 되돌릴 수 있습니다.

즉, 트랜잭션은 데이터의 정합성일관성을 지키기 위한 안전장치입니다.

 

자 그럼 트랜잭션이 필요한 순간들은 무엇이 있을까요?

위에서 말했지만, 실무적인 예시를 통하여 말씀드려보겠습니다.

- 상품을 수정하면서 카테고리, 옵션, 재료 정보까지 함께 수정
- 결제가 완료되면 주문 상태 변경 + 재고 차감 + 발주 요청 - 회원 가입 시 사용자 정보 + SNS 인증 정보 + 초기 설정값 삽입

 

이런 경우는 "하나라도 실패하면 전체 롤백"되어야 하므로 트랜잭션이 필수입니다.


NestJS에서 queryRunner로 트랜잭션 시작하기

const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();

try {
  // 트랜잭션 내 DB 작업
  const saved = await queryRunner.manager.save(...);

  await queryRunner.commitTransaction();
  return saved;
} catch (err) {
  await queryRunner.rollbackTransaction();
  throw err;
} finally {
  await queryRunner.release();
}

 

queryRunner.manager를 통해 트랜잭션 안에서만 동작하는 EntityManager 사용 가능합니다.


주의할 점

항목 설명
release() 누락 금지 커넥션이 반환되지 않아 커넥션 누수 발생
트랜잭션 시간 최소화 1초 이상 유지되면 DB 락이 길게 유지돼 병목 발생 가능
bulk insert/delete 지양 삭제 후 삽입보단, 수정/추가/삭제 분리 처리
병렬 트랜잭션 처리 시 주의 한정된 커넥션 풀에서 동시 트랜잭션이 많으면 Too many connections 에러 발생
예외 발생 시 즉시 rollback try-catch로 감싸고 rollbackTransaction 필수

 


마무리 

서비스가 커지고 데이터 흐름이 복잡해질수록, 트랜잭션의 중요성은 더욱 커집니다.
단순히 "성공/실패"를 나누는 수준이 아닌, 서비스 전반의 신뢰성과 데이터 일관성을 보장하는 핵심 메커니즘입니다.

NestJS와 TypeORM의 `queryRunner`를 잘 활용하면,
안정적인 서비스 아키텍처를 구축하는 데 큰 도움이 됩니다.


참고링크

https://cherrypick.co.kr/typeorm-basic-transaction/
https://orkhan.gitbook.io/typeorm/docs/transactions

 

Transactions | typeorm

docsTransactions Creating and using transactions Transactions are created using DataSource or EntityManager. Examples: Copyawait myDataSource.transaction(async (transactionalEntityManager) => { // execute queries using transactionalEntityManager }) or Copy

orkhan.gitbook.io

https://ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4_%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98

 

데이터베이스 트랜잭션 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 데이터베이스 트랜잭션(database transaction)은 DBMS 또는 유사한 시스템에서 상호작용의 단위 또는 일련의 연산이다. 여기서 유사한 시스템이란 트랜잭션의 성공과

ko.wikipedia.org

 

https://ko.wikipedia.org/wiki/%ED%8A%B8%EB%9E%9C%EC%9E%AD%EC%85%98

 

트랜잭션 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 트랜잭션(transaction)은 다음을 가리킨다. <!-- NewPP limit report Parsed by mw‐web.codfw.main‐5bd556c7bd‐lzv5w Cached time: 20250515050433 Cache expiry: 2592000 Reduced expiry: false Complicatio

ko.wikipedia.org

 

Comments