[Spring] @Transactional 어노테이션 동작방식
Spring

[Spring] @Transactional 어노테이션 동작방식

728x90

서버개발을 하다보면 특히 DB와 연동되는 부분에서 @Transactional 어노테이션이 자주 쓰입니다.

어노테이션을 붙여주는 것만으로도 DB에 수행되는 쿼리들을 하나의 transaction으로 묶어줄 수 있으며, 속성에 따라서는 exception 종류에 따라 rollback 도 가능합니다.

 

어떻게 어노테이션을 붙여주는 것만으로도 이것이 가능할까요? 지금부터 알아봅시다.


@Transactional 어노테이션은 Proxy 방식으로 동작한다

"어노테이션을 붙여서 Proxy 방식으로 동작한다" 어디서 많이 보시지 않았나요? 네 맞습니다. @Transactional 어노테이션은 Spring AOP의 대표적인 예입니다. 혹시 AOP에 대해 아직 모르신다면 아래 글을 먼저 읽고 와주세요!

[Spring] AOP - 관점 지향 프로그래밍 이란?

[Spring] Spring AOP 프록시 - JDK Proxy(JDK Dynamic Proxy), CGLib

 

따라서 기존 코드를 바꾸지 않고도, AOP proxy가 기존 코드를 가로채서 앞 뒤로 transaction 처리를 할 수 있는 코드를 배치해서 하나의 transaction 으로 처리될 수 있는 것이죠.

@Service
@RequiredArgsConstructor
public class SampleService {

    public void insertData(){
        // do something
    }
}

예를 들어 위와같은 서비스 로직이 하나 있다고 가정해봅시다. 만약 insertData 메소드에 @Transactional 어노테이션을 붙이게 되면

public class TransactionProxy{
    private final TransactonManager manager = TransactionManager.getInstance();

    public void transactionLogic() {
        try {
           manager.begin(); // 트랜잭션 전처리(트랜잭션 시작, autoCommit(false) 등)
           insertData(); // 기존 로직
           manager.commit(); // 트랜잭션 후처리(트랜잭션 커밋 등)
        } catch ( Exception e ) {
            manager.rollback(); // 트랜잭션 오류 발생 시 롤백
        }
    }

위 메소드에 대한 호출이 들어왔을 때 AOP proxy가 이를 가로채서 위와 같은 형태로 실행을 시키도록 해줍니다. 


주의할 점 

1. 메소드가 private 으로 돼있으면 @Transactional 어노테이션을 사용할 수 없습니다.

프록시 객체는 타겟 객체/인터페이스를 상속 받아서 구현하는데, private으로 되어 있으면 자식인 프록시 객체에서 호출할 수 없습니다. 따라서 @Transactional 이 붙는 메소드, 클래스는 프록시 객체에서 접근 가능한 레벨로 지정해야 합니다.

 

2. 트랜잭션은 객체 외부에서 처음 진입하는 메소드를 기준으로 동작합니다.

@transactional 어노테이션이 붙은 메소드 안에 어떤 메소드를 호출하는데 그 메소드에도 @Transactional 어노테이션이 붙어있을 수 있습니다. 하지만 AOP proxy는 호출시점에 target을 가로채기때문에 처음 진입하는 메소드를 기준으로만 동작합니다. 

 

출처:
- AOP와 @Transactional의 동작 원리
- [Spring] @Transactional의 이해
728x90