@Transactional과 Proxy 01

PPakSSam·2022년 1월 15일
1

@Transactional과 Proxy 목차


JPA는 트랜잭션 안에서 작동을 한다. 그리고 그 트랜잭션을 생성하도록 도와주는 것이 바로 @Transactional이다. 그동안 @Transactional을 무의식적으로 사용만 했었지 제대로 공부를 해본적은 없는 것 같아 여기에 공부한 내용을 적어두고자 한다.

@Transactional과 Proxy객체 주입

다음과 같은 TransactionService가 있다고 해보자.

@Service
@RequiredArgsConstructor
public class TransactionService {

    private final PostRepository postRepository;
    private final EntityManager em;

    public void runPersist(Post post) {
        transactionalPersistSave(post);
    }

    public void runRepository(Post post) {
        transactionalRepositorySave(post);
    }

    @Transactional
    public void transactionalPersistSave(Post post) {
        em.persist(post);
        System.out.println("영속화 여부: " + em.contains(post));
    }

    @Transactional
    public void transactionalRepositorySave(Post post) {
        postRepository.save(post);
        System.out.println("영속화 여부: " + em.contains(post));
    }
}

그리고 다음과 같이 테스트코드를 작성해보자.

@SpringBootTest
public class TransactionalTest {

    @Autowired TransactionService transactionService;
    @Autowired ApplicationContext applicationContext;

    @Test
    @DisplayName("과연 transactionService 객체는 프록시인가")
    public void proxyTest() throws Exception {

        String className 
            = applicationContext
            .getBean(transactionService.getClass())
            .getClass().getName();
            
        System.out.println(className);
    }
}

위의 테스트코드를 실행하면 다음과 같이 출력된다.

com.jpa.basic.test.transactional.TransactionService$$EnhancerBySpringCGLIB$$b6802bbc

CGLIB 프록시 객체를 생성하는 라이브러리이므로 transactionService에 프록시 객체가 주입되었음을 알 수 있다.

이제 @Transactional을 달면 어떻게 프록시 객체가 생성되는지 그 과정에 대해서 알아보자.

  1. 어플리케이션이 시작되면 @Transactional 어노테이션을 스캔한다.

  2. 만일 하나의 메소드라도 @Transactional이 붙어있다면 스프링 컨테이너는 시작할 때 해당 클래스의 프록시 객체를 생성하여 빈으로 등록한다.

  3. 의존성 주입을할 때 실제객체가 아닌 프록시 객체를 주입한다.

여기서 중요한 것은 하나라도 @Transactional이 있으면 스프링 컨테이너가 프록시 객체를 생성하여 빈으로 등록한다는 점이다. 이 부분에 대해서 많은 구글링을 해도 자료가 나오지 않아 직접 실험해서 도출해낸 결론이다.

만약에 위의 TransactionService에서 @Transactional을 모두 없애고 위의 테스트 코드를 실행하면 다음과 같은 결과가 나온다.

com.jpa.basic.test.transactional.TransactionService

프록시 객체가 아닌 실제 객체가 주입됨을 알 수 있다.

profile
성장에 대한 경험을 공유하고픈 자발적 경험주의자

0개의 댓글