private 메서드는 트랜잭션 처리를 할 수 없는 이유

2023. 7. 26. 16:58Spring

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