ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • private 메서드는 트랜잭션 처리를 할 수 없는 이유
    스터디/Spring 2023. 7. 26. 16:58
    728x90

    의문

     

    private 메서드는 @Transactional을 적용할 수 없다. 뭔가 예상이 가지만 그래도 한번 알아보자!!

     

    먼저 @Transactional 부터 살펴보자!

     

     

    @Transactional

    평소에 저희가 자주 사용하는 @Transactional에는 AOP가 적용되어있습니다.

     

    이를 스프링 트랜잭션 AOP라고 합니다.

    스프링 트랜잭션 AOP는 @Transactional이 붙여진 메서드가 실행되기 전에 begin을 호출하고 메서드가 종료한 뒤에 commit을 호출합니다!

     

    어떻게 할 수 있는 걸까요??

     

    답은 프록시입니다!!

     

     

    Spring에는 두가지 프록시 구현체가 있는 데 Springboot에서는 CGLIb를 사용하기 때문에 CGLIb를 기준으로 설명하겠습니다!

     

     

    아래는 에코노베이션 동아리에서 진행중인 도토링 프로젝트의 회원가입 코드의 일부입니다.

     

     

    @Transactional
    public void saveMento(MentoSignupRequestDTO mentoSignupRequestDTO, List<Certification> certifications){
        Mento mento = Mento.createMento(...);
        mentoRepository.save(mento);
    }
    

     

    코드에서 알 수 있듯이 트랜잭션이 적용되어있습니다!

     

     

    위 saveMento 메서드를 호출하면 아래와 같은 일들이 벌어집니다.

     

     

    (MentoService는 필자가 구현한 Service 클래스이고, MentoServiceProxy는 CGLIb가 만들어준 것이다.)

    아래는 CGLIb가 Enhancer 클래스를 바탕으로 Proxy를 생성하는 예시이다.

     

    // 1. Enhancer 객체를 생성
    Enhancer enhancer = new Enhancer();
    
    // 2. setSuperclass() 메소드에 프록시할 클래스 지정
    enhancer.setSuperclass(MentoService.class);
    enhancer.setCallback(NoOp.INSTANCE);
    
    // 3. enhancer.create()로 프록시 생성
    Object mentoServiceProxy = enhancer.create();
    
    // 4. 프록시를 통해서 간접 접근
    MentoService mentoService = (MentoService)mentoServiceProxy;
    mentoService.saveMento(mentoSignupRequestDTO);
    

     

    class MentoServiceProxy{
    
    	MentoService mentoSerivce;
    
    	@Override
    	public void saveMento(MentoSignupRequestDTO mentoSignupRequestDTO, List<Certification> certifications){
    		// begin 실행
    		mentoService.saveMento(MentoSignupRequestDTO mentoSignupRequestDTO, List<Certification> certifications);
    		// commit 실행
    	}
    
    }
    
    • setCallback 메서드는 프록시 클래스가 메서드를 사용할 수 있게 도와주는 클래스이다!

     

    즉, @Transactional을 적용하면, 타켓을 구현한 프록시 객체를 통해서 공통적인 전후 과정을 처리해주는 것을 알 수 있습니다.

     

     

    결론

     

    아마 다들 눈치채셨겠지만, private 메서드가 트랜잭션이 적용이 안 되는 이유는 타켓 객체의 메서드를 호출할 수 없기때문입니다.

    생각보다 간단한 결론이었지만, 이 과정을 통해서 프록시와 CGLIb에 대해서 공부할 수 있었습니다!!

     

    728x90
Designed by Tistory.