minOS

트랜잭션 문제 해결 - 트랜잭션 AOP 이해 본문

TIL/김영한의 스프링 DB 1편

트랜잭션 문제 해결 - 트랜잭션 AOP 이해

minOE 2024. 12. 7. 13:16
728x90

트랜잭션 AOP 이해

- 지금까지 트랜잭션을 편리하게 처리하기 위해서 트랜잭션 추상화도 도입하고, 추가로 반복적인 트랜잭션 로직을해결하기 위해 트랜잭션 템플릿도 도입했다.
- 트랜잭션 템플릿 덕분에 트랜잭션을 처리하는 반복 코드는 해결할 수 있었다. 하지만 서비스 계층에 순수한 비즈니스 로직만 남긴다는 목표는 아직 달성하지 못했다.
- 이럴 때 스프링 AOP를 통해 프록시를 도입하면 문제를 깔끔하게 해결할 수 있다.

 

프록시 도입하기

서비스의 로직에서 트랜잭션을 직접 시작한다.


서비스 계층의 트랜잭션 사용 코드 예시
// 트랜잭션 시작
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());

try {
    // 비즈니스 로직
    bizLogic(fromId, toId, money);
    transactionManager.commit(status); // 성공 시 커밋
} catch (Exception e) {
    transactionManager.rollback(status); // 실패 시 롤백
    throw new IllegalStateException(e);
}​

 

 

 

프록시 도입한 후

프록시를 사용하면 트랜잭션을 처리하는 객체비즈니스 로직을 처리하는 서비스 객체를 명확하게 분리할 수 있다.

트랜잭션 프록시 코드 예시
public class TransactionProxy {

    private MemberService target;

    public void logic() {
        // 트랜잭션 시작
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
            // 실제 대상 호출
            target.logic();
            transactionManager.commit(status); // 성공 시 커밋
        } catch (Exception e) {
            transactionManager.rollback(status); // 실패 시 롤백
            throw new IllegalStateException(e);
        }
    }
}

 

트랜잭션 프록시 적용 서비스 코드 예시

public class Service {

    public void logic() {
        // 순수 비즈니스 로직만 남음
        bizLogic(fromId, toId, money);
    }
}

 

- 프록시 도입 전: 서비스에 비즈니스 로직과 트랜잭션 처리 로직이 함께 섞여있다.
- 프록시 도입 후: 트랜잭션 프록시가 트랜잭션 처리 로직을 모두 가져간다. 그리고 트랜잭션을 시작한 후에 실제 서비스를 대신 호출한다. 트랜잭션 프록시 덕분에 서비스 계층에는 순수한 비즈니즈 로직만 남길 수 있다.

 

 

스프링이 제공하는 트랜잭션 AOP

- 스프링이 제공하는 AOP 기능을 사용하면 프록시를 매우 편리하게 적용할 수 있다. 
- 물론 스프링 AOP를 직접 사용해서 트랜잭션을 처리해도 되지만, 트랜잭션은 매우 중요한 기능이고, 전세계 누구나 다 사용하는 기능이다. 스프링은 트랜잭션 AOP를 처리하기 위한 모든 기능을 제공한다. 스프링 부트를 사용하면 트랜잭션 AOP를 처리하기 위해 필요한 스프링 빈들도 자동으로 등록해준다.
- 개발자는 트랜잭션 처리가 필요한 곳에 `@Transactional` 애노테이션만 붙여주면 된다. 스프링의 트랜잭션 AOP는 이 애노테이션을 인식해서 트랜잭션 프록시를 적용해준다.


@Transactional

org.springframework.transaction.annotation.Transactional

참고

스프링 AOP 적용하려면 어드바이저, 포인트컷, 어드바이스가 필요하다. 스프링은 트랜잭션 AOP 처리를 위해

다음 클래스를 제공한다. 스프링 부트를 사용하면 해당 빈들은 스프링 컨테이너에 자동으로 등록된다.


어드바이저
: `BeanFactoryTransactionAttributeSourceAdvisor`

포인트컷: `TransactionAttributeSourcePointcut`

어드바이스: `TransactionInterceptor`

 

728x90