본문 바로가기
개발

@Transactional을 붙이면 어떤 일이 일어나는가?

by hxxyeoniii 2025. 12. 2.
@Transactional을 붙이면 어떤 일이 일어나는가?

 

 

 

 

스프링의 @Transactional은 AOP를 기반으로 동작한다. 그리고 AOP의 구현 방식은 프록시에 있다.

스프링이 프록시를 통해 메서드 호출을 가로채고, 트랜잭션의 시작 & 커밋 & 롤백을 대신 처리해준다.

 

 

 

@Transactional의 함정, 내부 호출?

@Service
public class OrderService {

    // 트랜잭션 없음
    public void processOrder(Order order) {
        // 같은 클래스의 메서드를 직접 호출
        this.createOrder(order); // 트랜잭션 적용 X !!!
    }

    @Transactional
    public void createOrder(Order order) {
        orderRepository.save(order);
    }
}

-> processOrder는 this.createOrder를 호출한다.

-> 여기서 this는 프록시 객체가 아닌 실제 객체로, 트랜잭션 로직이 끼어들지 못한다.

 

 

 

따라서, 클래스를 분리하거나 @Autowired로 자기 자신을 주입받아 프록시를 통해 호출해야 한다.

// 권장: 클래스 분리
@Service
@RequiredArgsConstructor
public class OrderFacade {
    private final OrderService orderService;

    public void processOrder(Order order) {
        orderService.createOrder(order); // 프록시를 통해 호출
    }
}

@Service
public class OrderService {
    @Transactional
    public void createOrder(Order order) {
        orderRepository.save(order);
    }
}

 

 

 

 

그렇다면 롤백은 언제 일어나는가?

-> 기본적으로 스프링은 Unchecked Exception(RuntimeException과 그 하위 클래스)에서만 롤백된다.

 

 

 

checked Exception에서도 롤백을 수행하려면?

-> rollbackFor 속성을 사용해야 한다.

@Transactional(rollbackFor = Exception.class)
public void createOrder(Order order) throws IOException {
    orderRepository.save(order);
    throw new IOException("파일 처리 실패"); // 롤백 O
}

 

 

 

 

 

출처 : https://velog.io/@querydaily/Spring-Transactional-%EA%B7%B8%EB%83%A5-%EB%B6%99%EC%9D%B4%EC%8B%9C%EB%82%98%EC%9A%94

참고 : https://hxxyeoniii.tistory.com/53