Service단에서 주로 사용하는 @Transactional(readOnly=true)에 대해서 정리할 겸
@Transactional을 정리해보고자 한다.
우선 Transactional의 기본 docs를 살펴보자
@Transactional은 어떻게 동작하는가?
우리가 Transactional을 적용한다는 것은 애플리케이션이 돌아가면서 UncheckedException이 발생하면 rollback을 진행하도록 의도하고자 작성하는 Annotation이다.
Transactional을 확인하면 위의 rollback 행위를 AOP가 도와주는 상황으로 알 수 있다.
@Transactional이 없는 경우에는 CglibAopProxy가 등장한다.
CGLIB는 무엇인가?
https://www.youtube.com/watch?v=MFckVKrJLRQ
CGLIB는 Code Generator Libray의 약자이다.
클래스 기반으로 바이트 코드를 조작하여 프록시를 생성한다.
일반적인 다이나믹 프록시와 달리 인터페이스가 아닌 클래스 대상으로 동작하며 바이트코드를 조작해서 프록시를 만들기 때문에 다이나믹 프록시에 비해 성능이 우수하다는 장점이 존재하지만 상속 방식의 proxy화 할 메소드를 오버라이딩하는 방식인 만큼 final/private를 상속하는 객체에 오버라이딩을 지원하지 않는 경우 해당 메소드에 Aspect를 적용 할 수 없다.
@Transactional이 존재하는 경우는?
CglibAopProxy가 등장하면서 TransactionInterceptor가 등장하는 것을 확인 할 수 있다.
그럼 proxy안에서 돌아가는 코드는 다양하지만 몇가지만 확인해보자
- invocation.proceedWithinInvocation() : 실제 코드가 동작하는 부분이다.
- 오류 발생 시 complete TransactionAfterThrowing 안에서 rollback이 일어난다.
- 오류에 따라서 rollback의 실행 유무가 결정된다.
- 이 때 상태가 저장되며, ThreadLocalStorage를 사용한다.
- 성공시 commitTransactionAfterRunning이 실행되며 commit이 발생한다.
이때 주의해야하는 부분은 proxy에 대한 부분이다.
proxy는 Annotaion이 존재하는 아이가 호출될 때 생성된다.
그렇기에 Service단에 @Transactional(readOnly = true)를 적용하고, write의 행위 중 rollback을 진행하고 싶다면 따로 @Transactional을 붙여준다. 만약에 전체를 감싸지 않고 따로 각각 진행하면 어노테이션이 붙지 않은 애들은 프록시의 영향을 받지 못한다. + @Transactional(readOnly = true)는 성능상의 이점도 있기에 꼭 붙이고 진행하자.
참고 URL
https://techblog.woowahan.com/2606/
'개발 > Spring' 카테고리의 다른 글
@Transactional에 대한 정리[3] - rollback()에 관하여 (0) | 2023.09.11 |
---|---|
@Transactional에 대한 정리[2] - (readOnly=true)에 관하여 (0) | 2023.09.11 |
[Spring Security] @Secured(ROLE_?) (0) | 2023.01.13 |
Security + JWT를 사용해보자 (0) | 2023.01.10 |
[Security] JWT와 JWS는 뭘까...? (0) | 2023.01.06 |