private 메서드, @Transactional 동작할까?

슈퍼콜라·2025년 4월 29일
0

결론부터 말하면 동작하지 않는다

Spring에서는 @Transactional, @Cacheable, @Async 같은 애너테이션이 런타임에 동작하는 Spring AOP 기반으로 처리된다.

Spring AOP는 JDK Dynamic Proxy나 CGLIB 방식을 이용해 프록시 객체를 생성하고, 메서드 호출 전후로 횡단 관심사를 적용한다.

스프링은 빈을 생성할 때, 해당 클래스에 AOP 애너테이션이 존재하는지 검사한 후, 존재하면 프록시 객체로 감싸서 등록한다.

따라서 @Transactional 같은 애너테이션이 하나라도 선언되어 있는 클래스는 무조건 프록시로 감싸지게 된다.

@Slf4j
@RequiredArgsConstructor
@Service
public class SelfInvocation {

    private final MemberRepository memberRepository;

    public void outerSaveWithPublic(Member member) {
        saveWithPublic(member);
    }

    @Transactional
    public void saveWithPublic(Member member) {
        log.info("call saveWithPublic");
        memberRepository.save(member);
        throw new RuntimeException("rollback test");
    }

    public void outerSaveWithPrivate(Member member) {
        saveWithPrivate(member);
    }

    @Transactional
    private void saveWithPrivate(Member member) {
        log.info("call saveWithPrivate");
        memberRepository.save(member);
        throw new RuntimeException("rollback test");
    }
}

위 코드에서 saveWithPublic 메서드는 public 접근 제어자이기 때문에 프록시를 통해 트랜잭션이 적용된다.
반면 saveWithPrivate 메서드는 private 접근 제어자이기 때문에 트랜잭션이 적용되지 않는다.

또한, 같은 클래스 내에서 메서드를 호출하는 경우(Sefl Invocation)에는 프록시를 거치지 않고 직접 호출하게 되어 트랜잭션 어드바이스가 적용되지 않는다.

테스트 결과 요약
외부에서 selfInvocation.saveWithPublic()을 직접 호출하면 트랜잭션이 정상 동작하고 롤백된다.
outerSaveWithPublic()처럼 내부 메서드를 통해 호출하면 트랜잭션이 적용되지 않아 롤백이 되지 않는다.
private 메서드는 애초에 AOP 적용 대상이 아니기 때문에 트랜잭션이 적용되지 않는다.

profile
공부하는거 정리

0개의 댓글