legacy/Spring

[Spring] 트랜잭션 전파, Propagation.REQUIRES_NEW

heemang.dev 2023. 9. 6. 14:03

 

앞서 여기서 외부 트랜잭션과 내부 트랜잭션에 대해 설명하였다. 트랜잭션 참여에 대해서 설명을 하였는데, 이번에는 트랜잭션 참여가 아닌 새로운 트랜잭션 생성에 대해서 알아보자.

 

트랜잭션 참여

@Transactional을 사용할 때 옵션으로 propagation = Propagation.REQUIRED를 사용한다.

@Transactional(propagation = Propagation.REQUIRED)
public class MemberRepository {
 	// 생략
    }

새로운 트랜잭션 생성

@Transactional을 사용할 때 옵션으로 propagation = Propagation.REQUIRES_NEW를 사용한다.

@Transactional(propagation = Propagation.REQUIRES_NEW)
public class LogRepository {
	// 생략
    }

트랜잭션 롤백

내부 트랜잭션과 달리 외부 트랜잭션에서 롤백이 호출된다면 사용 중인 커넥션에 rollbackOnly를 표시하지 않는다. 

LogRepository의 경우 MemberService에서 시작된 트랜잭션에 참여하지 않고 새로운 트랜잭션을 생성한다. 따라서 LogRepository에서 시작된 트랜잭션은 외부 트랜잭션이다. 여기서 롤백이 호출되더라도 커넥션에 rollbackOnly를 표시하지 않고 바로 롤백 처리를 해버린다.

 

MemberService는 LogRepository로부터 넘어온 예외를 try-catch로 처리한다. 내부 트랜잭션(MemberRepository)에서 커밋을 하였기 때문에 외부 트랜잭션에서도 문제없이 커밋을 요청한다. 이때 사용 중인 커넥션을 확인하는데 rollbackOnly 표시가 없기 때문에 외부 트랜잭션 또한 정상적으로 커밋을 호출하게 된다.


결론

LogRepository가 트랜잭션에 참여하던 때에는 MemberService에서 사용하는 커넥션에 rollbackOnly가 붙기때문에 커밋을 요청하더라도 롤백을 처리해야 했다. 그러나 새로운 트랜잭션을 생성하면서 LogRepository에서 롤백을 하더라도 자신만 사용하는 트랜잭션이기 때문에 rollbackOnly를 표시하지 않고 바로 롤백처리를 하게 된다. 따라서 MemberService에서 사용하는 트랜잭션은 커밋을 정상적으로 수행하게 된다.