스프링 트랜잭션의 적용과 확인방법

2023. 3. 15. 16:31개발

반응형

개인적인 정리입니다....!
모든 내용은 인프런에 있는 김영한님 강의 중 스프링 DB 2편에 나오는 내용입니다.

스프링에서 제공하는 트랜잭션을 사용 하기위헤서는 해당 트랜잭션을 적용하는 방식에 대해서 알아야 하는데…

@Transactional

스프링의 경우에는 위의 Transactional 어노테이션을 명시하여 사용하고 이 경우를 선언적 트랜잭션 관리라고 한다. 다양한 방식이 존재하지만 현재는 해당방식을 가장 많이 사용한다.(Proxy 방식의 AOP가 적용된다.) 이전 회사에서는 서비스단의 메서드 이름에 대해 컨벤션을 지정해놓고 프로그래밍단에서 트랜잭션이 어떤 것이 사용 될지에 대해 스프링 실행시에 지정되도록 되어 있었다. (예를들어 select로 시작하는 경우 readOnly 적용 update 시작 되는 경우 수정도 가능하게 트랙잭션 옵션이 설정되는 형식)

선언적 트랜잭션으로 관리할 경우 원하면 트랜잭션 어노테이션을 붙이고 불필요하다고 생각되면 제거하면 되는 형태로 매우 직관적이고 편하게 사용가능하다..!

김영한님의 강의에서 설명해준 프록시 형태의 트랜잭션이 적용되는걸 보여주는 이미지이다.

만약 실제로 AOP기반 트랜잭션이 적용되고 있는지 궁금 할 때 확인하고 싶은경우에는 어떻게 해야할까?

특정클래스에 어노테이션이 선언되어 있는경우 getClass를 해서 호출해보면 실제 클래스의 메모리 주소가 아닌 spring boot AOP가 적용되어 프록시를 적용하기 위해 CGLIB로 되어있는 주소를 가져오게 된다.

그리고 AopUtils.isAopProxy로 적용 여부를 boolean 값으로 확인 가능하다.

@Autowired
BasicService basicService;

//로그 호출
log.info("aop class = {}", basicService.getClass());
boolean aopProxy = AopUtils.isAopProxy(basicService);
//로그에 찍힌 내용
aop class = class hello.springtx.apply.TxBasicTest$BasicService$$EnhancerBySpringCGLIB$$e5426675

그리고 만약 트랜잭션이 적용되었는지 확인하고 싶다면..?

TransactionSynchronizationManager에 있는 메서드를 사용하여 동일하게 체크 할 수 있다.

트랜잭션 어노테이션이 선언되어 있는 경우 true로 값이 반환되는걸 확인 할 수 있다..!!!

명시적으로 확인하고 싶다면 사용하도록 하자!

boolean txActive = TransactionSynchronizationManager.isActualTransactionActive();

프록시가 사용되는 형태의 경우에는 직접 만들기 힘들어서 강의 내 이미지를 그대로 가져왔다.

특정 로직에서 트랜잭션이 선언된 클래스의 메서드를 의존성 주입을 받아 호출하게 되면 해당 클래스를 직접 호출하는게 아닌 해당객체를 상속받은 프록시 객체를 호출하게되고..! 거기에는 AOP기반의 트랜잭션이 적용되어 있는 것이다….!

상세하게 트랜잭션이 어떻게 이뤄지는지 확인하고 싶다면 application.properties에 추가 설정을 넣어야 한다. (트랜잭션 프록시가 호출하는 트랜잭션의 시작과 종료를 명확하게 알 수 있도록 로그를 남겨준다.)

logging.level.org.springframework.transaction.interceptor=TRACE
@Transactional

스프링의 경우에는 위의 Transactional 어노테이션을 명시하여 사용하고 이 경우를 선언적 트랜잭션 관리라고 한다. 다양한 방식이 존재하지만 현재는 해당방식을 가장 많이 사용한다.(Proxy 방식의 AOP가 적용된다.) 이전 회사에서는 서비스단의 메서드 이름에 대해 컨벤션을 지정해놓고 프로그래밍단에서 트랜잭션이 어떤 것이 사용 될지에 대해 스프링 실행시에 지정되도록 되어 있었다. (예를들어 select로 시작하는 경우 readOnly 적용 update 시작 되는 경우 수정도 가능하게 트랙잭션 옵션이 설정되는 형식)

선언적 트랜잭션으로 관리할 경우 원하면 트랜잭션 어노테이션을 붙이고 불필요하다고 생각되면 제거하면 되는 형태로 매우 직관적이고 편하게 사용가능하다..!

김영한님의 강의에서 설명해준 프록시 형태의 트랜잭션이 적용되는걸 보여주는 이미지이다.

만약 실제로 AOP기반 트랜잭션이 적용되고 있는지 궁금 할 때 확인하고 싶은경우에는 어떻게 해야할까?

특정클래스에 어노테이션이 선언되어 있는경우 getClass를 해서 호출해보면 실제 클래스의 메모리 주소가 아닌 spring boot AOP가 적용되어 프록시를 적용하기 위해 CGLIB로 되어있는 주소를 가져오게 된다.

그리고 AopUtils.isAopProxy로 적용 여부를 boolean 값으로 확인 가능하다.

@Autowired
BasicService basicService;

//로그 호출
log.info("aop class = {}", basicService.getClass());
boolean aopProxy = AopUtils.isAopProxy(basicService);
//로그에 찍힌 내용
aop class = class hello.springtx.apply.TxBasicTest$BasicService$$EnhancerBySpringCGLIB$$e5426675

그리고 만약 트랜잭션이 적용되었는지 확인하고 싶다면..?

TransactionSynchronizationManager에 있는 메서드를 사용하여 동일하게 체크 할 수 있다.

트랜잭션 어노테이션이 선언되어 있는 경우 true로 값이 반환되는걸 확인 할 수 있다..!!!

명시적으로 확인하고 싶다면 사용하도록 하자!

boolean txActive = TransactionSynchronizationManager.isActualTransactionActive();

프록시가 사용되는 형태의 경우에는 직접 만들기 힘들어서 강의 내 이미지를 그대로 가져왔다.

특정 로직에서 트랜잭션이 선언된 클래스의 메서드를 의존성 주입을 받아 호출하게 되면 해당 클래스를 직접 호출하는게 아닌 해당객체를 상속받은 프록시 객체를 호출하게되고..! 거기에는 AOP기반의 트랜잭션이 적용되어 있는 것이다….!

프록시 적용되는 모습

세하게 트랜잭션이 어떻게 이뤄지는지 확인하고 싶다면 application.properties에 추가 설정을 넣어야 한다. (트랜잭션 프록시가 호출하는 트랜잭션의 시작과 종료를 명확하게 알 수 있도록 로그를 남겨준다.)

logging.level.org.springframework.transaction.interceptor=TRACE
logging.level.org.springframework.jdbc.datasource.DataSourceTransactionManager=TRACE

#JPA log
logging.level.org.springframework.orm.jpa.JpaTransactionManager=DEBUG
logging.level.org.hibernate.resource.transaction=DEBUG

 

그리고 트랜잭션 어노테이션의 경우 Service 클래스에도 사용 가능하고 특정 메서드에도 적용이 가능하다..

이런경우 어디에 선언된게 우선순위를 가지는가..? 에 대해서는 명확하게 설명해주신 글이 있었다..

더 구체적이고 자세한것이 높은 우선순위를 가진다!

클래스와 메서드 중 어디가 더 구체적인가? —> 메서드

인터페이스와 그걸 구현한 구현체중 어디가 더 구체적인가? —> 구현체

반응형