지금까지 @Transaction 어노테이션을 사용하면서, Repository 혹은 Service 클래스 중 한 곳만 @Transaction 어노테이션을 달아 트랜잭션 전파에 대해서 알지 못했다.
이번에 트랜잭션 중에 다른 트랜잭션이 동작하려고 할 때 어떤일이 일어나는지 스프링 트랜잭션 전파에 대해서 공부하게 되었다.
트랜잭션 내 다시말해 @Transactional 어노테이션이 붙어 있는 메서드 내에 내부 메서드가 있을 수 있다. 또한 해당 내부 메서드는 @Transactional 어노테이션이 붙어 있을 수 있다. 이 때 고려해야하는 부분이 스프링 트랜잭션 전파이다.!!
아래가 다음과 같은 예제이다.
// Service
...
@Transactional
public void join(String username) {
Member member = new Member(username);
Log logMessage = new Log(username);
memberRepository.save(member);
logRepository.save(logMessage);
}
@Repository
@RequiredArgsConstructor
public class MemberRepository {
private final EntityManager em;
@Transactional
public void save(Member member) {
em.persist(member);
}
...
}
@Repository
@RequiredArgsConstructor
public class LogRepository {
private final EntityManager em;
@Transactional
public void save(Log logMessage) {
em.persist(logMessage);
}
...
}
join() → 외부 트랜잭션 // memberRepository.save(member); logRepository.save(logMessage); → 내부 트랜잭션
트랜잭션 내에서 체크 예외 발생 → 커밋 // 런타임 예외 발생 → 롤백
해당 전파 방식을 통해 트랜잭션의 동기화를 할 수 있다. 하지만 만일 내부 트랜잭션이 커밋되든 롤백되든 상관없이 외부 트랜잭션이 커밋되기를 바랄 상황이 있을 것이다. 이는 @Transactional의 propogation 설정값중 Propagation.REQUIRES_NEW 로 설정하면 된다. 이는 기존 트랜잭션(외부 트랜잭션)이 있든 말든 새로운 트랜잭션이 생성되어, 기존 트랜잭션과 독립적인 트랜잭션을 만들어 로직을 수행시킬 수 있다.
https://www.inflearn.com/course/스프링-db-2/dashboard
https://techblog.woowahan.com/2606/