Notice
Recent Posts
Recent Comments
Link
관리 메뉴

look-forest

트랜잭션 전파 활용 본문

Spring/Spring 데이터 접근 - 활용 기술

트랜잭션 전파 활용

studyHub 2024. 9. 7. 17:41

트랜잭션 전파가 필요한 이유

Service단에서 트랜잭션 하나만 사용할 경우

  • 클라이언트 A만 생각하면 MemberService 에 트랜잭션 코드를 남기고, MemberRepository , LogRepository 의 트랜잭션 코드를 제거하면 깔끔하게 하나의 트랜잭션을 적용할 수 있다.
  • 하지만 이렇게 되면 클라이언트 B, C가 호출하는 MemberRepository , LogRepository 에는 트랜잭션을 적용 불가!

트랜잭션 전파 없이 이런 문제를 해결하려면 트랜잭션이 있는 메서드와 트랜잭션이 없는 메서드를 각각 만들어야 한다.

이런 문제를 해결하기 위해 트랜잭션 전파가 필요한 것이다.


트랜잭션 전파 활용

스프링은 @Transactional 이 적용되어 있으면 기본으로 REQUIRED 라는 전파 옵션을 사용한다. 이 옵션은 기존 트랜잭션이 없으면 트랜잭션을 생성하고, 기존 트랜잭션이 있으면 기존 트랜잭션에 참여한다.

'참여한다'는 뜻은 해당 트랜잭션을 그대로 따른다는 뜻이고, 같은 커넥션을 사용한다는 뜻이다.

모든 논리 트랜잭션을 커밋해야 물리 트랜잭션도 커밋된다. 하나라도 롤백되면 물리 트랜잭션은 롤백된다.
repository의 예외를 catch하지 않아서 service에도 전달된 경우. 참고로 이 경우 어차피 롤백이 되었기 때문에, rollbackOnly 설정은 참고하지 않는다.


트랜잭션 전파 활용 - 복구 REQUIRED, REQUIRES_NEW

문제 상황

회원 가입을 시도 로그를 남기는데 실패하더라도 회원 가입은 유지되어야 한다. REQUIRED_NEW 를 써야할까?

 

단순하게 생각해보면 LogRepository에서 예외가 발생하면 그것을 MemberService에서 예외를 잡아 처리하면 될 것 같다. 실무에서 많은 개발자가 이 방법을 사용해서 실패한다.

논리 트랜잭션은 하나라도 롤백되면 관련된 물리 트랜잭션은 롤백되어 버린다!

서비스 단에서 예외를 처리하더라도, 레파지토리 단의 트랜잭션은 예외가 발생하여 rollbackOnly=true로 설정했다.

서비스단은 예외가 없어서 커밋하려고 할때, rollbackOnly 설정 때문에 UnexpectedRollbackException 오류가 발생한다.

 

해결방법

이 문제를 해결하려면 REQUIRES_NEW 를 사용해서 트랜잭션을 분리해야 한다.

REQUIRES_NEW로 트랜잭션 분리 + 외부 트랜잭션 예외 CATCH

※ 주의

  • REQUIRES_NEW 를 사용하면 하나의 HTTP 요청에 동시에 2개의 데이터베이스 커넥션을 사용하게 된다. 따라서 성능이 중요한 곳에서는 이런 부분을 주의해서 사용해야 한다.
  • REQUIRES_NEW 를 사용하지 않고 문제를 해결할 수 있는 단순한 방법이 있다면, 그 방법을 선택하는 것이 더 좋다.
    예를 들면 다음과 같이 REQUIRES_NEW 를 사용하지 않고 구조를 변경하는 것이다.

이렇게 하면 HTTP 요청에 동시에 2개의 커넥션을 사용하지는 않는다. 순차적으로 사용하고 반환하게 된다.

 

물론 구조상 REQUIRES_NEW 를 사용하는 것이 더 깔끔한 경우도 있으므로 각각의 장단점을 이해하고 적절하게 선택해서 사용하면 된다.


참고 자료 & 이미지 출처
스프링 DB 2편 - 데이터 접근 기술 (김영한 님)


 

'Spring > Spring 데이터 접근 - 활용 기술' 카테고리의 다른 글

스프링 트랜잭션 전파  (0) 2024.09.07
스프링 트랜잭션 이해  (0) 2024.09.02
데이터 접근 기술 - 활용 방안  (2) 2024.09.02
QueryDSL : type-safe Query  (0) 2024.08.31
스프링 데이터 JPA  (0) 2024.08.18