트랜잭션 AOP

조승빈·2024년 12월 4일

Spring DB

목록 보기
5/8

Transactional flow

트랜잭션의 실행 과정은 다음과 같다.
기억해야 할 점은 AOP Proxy를 거친다는 점이다.

Proxy

AOP 기반 기능을 사용할 때 실제 객체 대신 프록시 객체가 생성되고 메서드 호출을 가로채서 트랜잭션을 처리한다.

클래스에 @Transactional이 하나라도 존재하는 경우 클래스의 Proxy 객체를 생성한다.

@Transactional이 하나라도 존재하는 경우 클래스의 Proxy 객체를 생성하는 이유
-> AOP는 기본적으로 클래스 또는 인터페이스 수준에서 동작하기 때문이다.

AOP 기능을 적용하기 위해 매서드 실행 전후로 특정 로직을 삽입해야 한다.
트랜잭션의 경우 트랜잭션을 시작하고 커밋하거나 롤백하는 로직이 필요한데 이 기능을 프록시가 수행한다.


예시 상황 1

@Service
public class MyService {
	public void outerMethod() {
    	// 비지니스 로직
        innerMethod();
    }
    
    @Transactional
    public void innerMethod() {
    	// 비지니스 로직
    }
}

이 상황에서 outerMethod를 호출할 경우 innerMethod의 트랜잭션이 작동하지 않는다.

예시 상황 1: 정상적인 호출 (innerMethod를 호출할 경우)

정상적인 호출의 경우 다음과 같다.

innerMethod를 호출할 경우 @Transactional이 있기 때문에 프록시 객체를 거쳐 트랜잭션이 적용된 후 함수를 실행한다.

예시 상황 1: 비정상적인 호출 (outerMethod를 호출할 경우)

만약 outerMethod를 호출한 경우 객체를 직접 호출하기 때문에 트랜잭션이 적용되지 않는다.

innerMethod@Transactional이 있으니까 innerMethod를 호출했을 때 프록시를 거쳐야 하는거 아닌가요??

  • java 언어에서 메서드 앞에 별도 참조가 없으면 this라는 뜻이다.
    따라서 자기 자신의 인스턴스인 targetinnerMethod를 가리킨다.

예시 상황 1: 해결 방법

이 예외를 해결하는 가장 간단한 방법은 클래스를 구분하는 것이다.
예를 들어 OuterClassInnerClass로 구분하면 이와같은 예외가 발생하지 않고 정상적으로 실행될 것이다.

  • 다른 방법으로는 프록시 객체를 사용해서 호출하는 방법, self 빈 주입 방법 등이 있다.

예시 상황 1-1

만약 둘 다 @Transactional이 존재하는 경우

@Service
public class MyService {
    @Transactional
	public void outerMethod() {
    	// 비지니스 로직
        innerMethod();
    }
    
    @Transactional
    public void innerMethod() {
    	// 비지니스 로직
    }
}

결론부터 말하자면 innerMethod도 트랜잭션이 적용된다.
하지만 이 경우에도 innerMethod를 호출할 때 역시 프록시를 거치는 것이 아니라 직접 호출되기 때문에 innerMethod@Transactional은 무시된다.

예시 상황 1-1: innerMethod에 트랜잭션이 적용되는 이유

  • outerMethod@Transactional이 적용되어 있으므로, 이미 트랜잭션이 활성화된 상태에서 innerMethod가 호출된다.
  • innerMethodouterMethod의 트랜잭션에 포함되어 실행된다.
  • 따라서 innerMethod도 트랜잭션이 적용된다.

예외 상황 2

@PostConstruct@Transactional을 함께 사용하면 트랜잭션이 적용되지 않는다.
@PostConstructSpring 빈 초기화 단계에서 실행되기 때문이다. 이 시점에서는 AOP가 적용되기 전에 메소드가 실행되기 때문에 트랜잭션을 적용할 수 없다.

profile
평범

0개의 댓글