조사 계기, 트랜잭션 발원지에 대한 궁금증
@EventListener / @TransactionalEventListener (+ @Async 유무)에서 트랜잭션의 동작에 대해 알아보고 있었다
그러가다 아래 트랜잭션 로그의 발원지가 궁금해졌다
로그를 따라가다 보니 친숙한 얼굴들이 보였다
그만 조금만 보고 나온다는게, 끝을 봐보자는 마음으로 살펴보게 되었다
사전 지식
나는 이미 어느 정도 코드의 내막을 알았지만 처음 본 사람은 어려울테니, 알게된 내용을 미리 정리했다
이걸 보고 들어가면 코드를 읽어나가기 좀 더 수월할 것이다!
TransactionAspectSupport (org.springframework.transaction.interceptor)
스프링의 AOP 기능으로 트랜잭션을 처리해주는 역할
실제 트랜잭션 매니징 처리는
Spring Web(Sync, Tomcat)의 경우는 PlatformTransactionManager에게
Reactive (Async, Netty)의 경우는 ReactiveTransactionManager에게
전략패턴으로 위임한다
AbstractPlatformTransactionManager (org.springframework.transaction.support)
인터페이스인 PlatformTransactionManager보다 더 구체적인 역할을 하고 실제로 트랜잭션 매니징을 하는 역할.
각 구현체(Hibernate등)는 이것을 일부 커스텀하게 구현할 수 있다
JpaTransactionManager (org.springframework.orm.jpa)
AbstractPlatformTransactionManager의 구현체. JPA와 관련된 트랜잭션 처리 로직을 담당한다
TransactionImpl (org.hibernate.engine.transaction.internal
트랜잭션과 관련된 오브젝트 .commit, rollback 등을 수행
SessionImpl (org.hibernate.internal)
엔티티 매니저의 구현체. 엔티티 매니저라고 봐도 된다.
엔티티 매니저 관련 로직을 볼때 이 클래스를 보면 된다!
ActionQueue (org.hibernate.engine.spi)
JPA에서 발생한 DML 이벤트 (insert, update, delete) 등을 보관하는 큐 객체이다
내부적으로 아래 필드들을 갖고 있다
해당 필드는 List of EntityAction로 구성되어 있는데, EntityAction의 구현체는 Command DML로 되어있다
AbstractFlushingEventListener (org.hibernate.event.internal)
JPA의 DML Flush(쓰기 지연소에 반영)을 처리 이벤트가 발생할 때 수신하는 이벤트객체
구현체로
DefaultFlushEventListener
DefaultDirtyCheckEventListener
DefaultAutoFlushEventListener
-가 있다
DefaultFlushEventListener (org.hibernate.event.internal)
JPA에서 Update 발생시 수신하는 이벤트 처리 객체
EventListenerGroupImpl (org.hibernate.event.service.internal)
JPA의 DML Action을 처리한 이벤트 리스너들을 담고 있는 그룹
JdbcCoordinator (org.hibernate.engine.jdbc.spi)
하이버네이트에서 사용하기 위한 JDBC관련된 동작을 정의
JdbcResourceLocalTransactionCoordinatorImpl (org.hibernate.resource.transaction.backend.jdbc.internal)
단일 트랜잭션 관리를 하기 위한 역할
TransactionCoordinator 인터페이스를 구현했고,
이것의 구현체는 위 클래스와 분산 트랜잭션 관리 역할인 JtaTransactionCoordinatorImpl가 있다
땅굴 조사
실제로 디버거를 타고 내려가는 과정은 그렇게 쉽지 않았다
거시적으로 보면 아래와 같이 분기처리를 탄다
코드로 보면 아래와 같다
메서드 호출 스택을 적으면서 코드로 보면 아래와 같다
TransactionAspectSupport .invokeWithinTransaction → commitTransactionAfterReturning →
AbstractPlatformTransactionManager .commit → processCommit →
JpaTransactionManager .doCommit →
TransactionImpl .commit →
JdbcResourceLocalTransactionCoordinatorImpl .commit →
JdbcResourceLocalTransactionCoordinatorImpl .beforeCompletionCallback →
JdbcCoordinatorImpl . beforeTransactionCompletion →
SessionImpl .beforeTransactionCompletion →
flushBeforeTransactionCompletion → managedFlush → doFlush →
EventListenerGroupImpl .fireEventOnEachListener →
DefaultFlushEventListener .onFlush →
AbstractFlushingEventListener .performExecutions →
ActionQueue .executeActions() → executeActions(ExecutableList<E>) →
AbstractEntityPersister .update →
UpdateCoordinatorStandard . performUpdate → doStaticUpdate
(이곳부터 정신을 잃기 시작했다… 의미를 알 수 없는 급하게 작성한 득한 느낌의 냄새가 풍기는 코드들이 등장하기 시작했다)
예외 발생의 경우
TransactionAspectSupport .invokeWithinTransaction →
completeTransactionAfterThrowing → rollback → processRollback → doRollback →
TransactionImpl .rollback → …
각 객체간 위임 흐름도
구체적으로 클래스를 나열해보면 아래 그림과 같이 끝없는 위임을 연속한다
그나마 간소화해서 표현하면 아래와 같다
더 요약하면!!
@Transactional에 의해 AOP가 걸리면 CGLib에 의해 TransactionAspectSupport가 호출되고
트랜잭션 매니저에게 위임한다.
그리고 Transaction 객체에 commit을 맡긴 후 Transaction 조정자에게 위임,
그리고 EntityManger에게 트랜잭션 처리를 위임해서 flush 단계까지 간다
이벤트 리스너 그룹에게 이벤트 처리를 맡긴다
단순 Update의 경우 DefaultFlushEventListener 가 맡아서 처리한다
그리고 ActuionQueue가 DML 이벤트 큐를 받아서 처리한다 (이 경우 update)
느낀점
정말 보면서 느낀거지만 Spring은 정돈 되지 않은 코드들은 있지만 문서화가 정말 잘 되어있다
Hibernate는 스프링만큼의 문서화가 잘 되어있지 않은 것 같다는 인상을 받았다
확장성도 조금 빈약하다는 생각이 들었다. 인터페이스와 구현 클래스들의 관계가 명확하지 않다는 인상을 받았다
HIbernate가 천천히 발전하는 이유가 이것 때문이 아닐까 ...
코드 베이스를 이해하는 사람들이 많아지면서 오픈 소스 컨트리뷰터들이 앞으로 적어지지 않을까 싶은 걱정이 있다
참고
같이 읽어보면 좋을 내용 ㅎ
(작성한 내용과 다른 부분을 다룬 내용들도 있음)
'Back-end > Spring Boot, JPA' 카테고리의 다른 글
스프링 배치 정리 (0) | 2024.04.27 |
---|---|
Quiz! 다음 코드에서 JPA가 실행하는 Query는? (0) | 2024.04.04 |
Spring Data Repository 확장 (짧음) (0) | 2023.12.13 |
Thread Safe하게 처리해보자 (feat. synchronized , 낙관, 비관, named) (0) | 2023.06.27 |
ArgumentResolver처리 과정 + Spring Web MVC 흐름 (0) | 2023.06.20 |
hi hello... World >< 가장 아름다운 하나의 해답이 존재한다
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!