-
private 메서드는 트랜잭션 처리를 할 수 없는 이유스터디/Spring 2023. 7. 26. 16:58728x90
의문
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'스터디 > Spring' 카테고리의 다른 글
Spring에서 Execption을 핸들링하는 방법 (0) 2024.01.15 DTO에 대한 고민 (0) 2023.07.17 Filter와 FilterChain에 대하여 알아보자 (0) 2023.04.07 Argument Resolver에 대해서 알아보자 (0) 2023.03.30 쓰레드 풀을 이용한 쓰레드 관리 (0) 2023.03.26