인프런 커뮤니티 질문&답변

Mpels님의 프로필 이미지
Mpels

작성한 질문수

탄탄한 백엔드 NestJS, 기초부터 심화까지

TypeORM 트랜잭션 질문드립니다.

해결된 질문

작성

·

658

·

수정됨

1

안녕하세요 윤상석 강사님. TypeORM의 트랜잭션 관련으로 질문이 있습니다.

TypeORM에서 트랜잭션을 다루는 방법은 이전 질문글에 답변해주셨듯이 크게 3가지인 것으로 알고 있습니다.

1. QueryRunner

2. getConnection, getManager

3. @Transactional

개인적으로는 @Transactional() 데코레이터를 사용하는것이 편리하여 사용하고 있었는데요.

NestJS 공식문서에서 데코레이터를 이용하는 것을 권장하지 않고 있고,

구글링을 해보아도 유닛 테스트에 어려움이 있어 권장하지 않는 분들이 많은 것을 알게되었습니다.

여기서  첫 번째 질문이 있습니다.

Q1. "유닛 테스트에 어려움이 있다"는 이야기가 구체적으로 무슨 의미인지 궁금합니다.

         모킹이 어렵다. 내 마음대로 제어가 불가능하다 등의 이야기가 이해는 가는데 와닿지는 않아서 질문드립니다.

----

QueryRunner 방식을 이용하게 되면 try-catch-finally 코드가 강제가 되는 것 같아보입니다.

여기서 두 번째 질문이 있습니다.

Q2. 모든 에러를 감지하는 Filter를 적용해두었다면 QueryRunner를 사용하는 try-catch-finally 구문에서 에러 처리를 해버려 필터가 작동하지 않을 것 같은데 맞을까요?

맞다면, 만약 Filter에서 요청이 실패하였을 때의 로깅기능이 있다고 가정한다면 로깅기능이 작동하지 않을 것 같습니다.

그렇다면 catch 문에서 따로 Filter에서 구현한 로깅을 다시 구현해주어야 할까요?

----

트랜잭션 처리를 도와주는 typeorm-transactional-cls-hooked 패키지를 발견하였습니다.

여기서 마지막 세 번째 질문이 있습니다.

Q3. 해당 패키지는 유닛 테스를 할 때 트랜잭션 기능이 작동하지 않도록 모킹기능도 제공해주는 것 같습니다.

         QuerryRunner 보다 안 좋은점이 있다면 어떤 점이 있을까요?

----

질문이 너무 많은 것 같아 죄송합니다.

좋은 강의와 답변해주셔서 항상 감사합니다.

답변 1

0

윤상석님의 프로필 이미지
윤상석
지식공유자

안녕하세요.

Q1.

유닛테스팅을 할 때에는 DI된 프로바이더를 실제로 사용하지 않고 모킹(실제 함수나 객체가 아닌 그런척을 하는 것들을 사용)하여 사용하는 경우가 많습니다. 모킹을 하는 이유는 외부 서비스에 의존하지 않고 독립적으로 테스트를 하기 위함입니다.

따라서 @Transactional 데코레이터를 사용하지 않고 쿼리러너를 사용하는 경우 쿼리러너를 모킹하여 사용하여 테스팅을 진행합니다. 데코레이터를 사용한 경우 따로 모킹하는 것이 어렵고 이 경우 세세한 부분에 있어서 테스팅이 상대적으로 어렵습니다.

 Q2.

사실 이 부분이 쿼리러너의 큰 단점인 것 같습니다. 쿼리러너를 사용하는 경우 에러 처리에 있어서 상대적으로 어렵습니다. 

try 안의 트랜젝션 각각에 대해서 throw Error("...")으로 던지고 트랜젝션 catch(error) 에서 에러를 받아 전부 throw BadRequestException(error)로 처리하여 필터로 넘겨도 되지만 사실 세세한 에러 처리는 조금 어렵습니다. 하지만 이 방법으로 하면 필터로 넘길 수 있어서 그 필터 안에서 로깅을 잡아 두면 해결됩니다.

Q3.

저 패키지는 들어보긴 했는데 제가 아직 깊게 사용해보지 않아서 확실하게는 말씀드리기 어려울 것 같습니다.

결론적으로,

데코레이터를 사용하지 않고 쿼리러너를 사용하는 가장 큰 이유는 좀 더 세세하게 트랜젝션 처리를 할 수 있다는 것과 테스팅의 편의성이 큰 것 같습니다.  그리고 @Transactional를 사용할때 가끔씩 이슈가 있었던 것으로 기억합니다.

Mpels님의 프로필 이미지
Mpels

작성한 질문수

질문하기