[만약 이 글을 읽기전 트랙잭션의 원리를 모른다면 이글을 참고하길 바란다]
[스프링] 트랜잭션의 이해와 활용,@Transactional 원리 - 기록만이 살길 (tistor
[스프링] 트랜잭션의 이해와 활용,@Transactional 원리 - 기록만이 살길
[🍊트랜잭션의 이해] [트랜잭션 이란 무엇인가?] - 트랜잭션의 이해 (tistory.com) [트랜잭션 이란 무엇인가?] - 트랜잭션의 이해 [🍓트랜잭션의 정의] 트랜잭션(Transaction)은 데이베이스의 상태를 변
thaud153.tistory.com
[🍊트랜잭션의 작동원리]
트랜잭션은 어떻게 작동하는걸까??
이 부분은 간단하면서 어려운 내용이다.
기본적으로 트랜잭션은 프록시라는 클래스를 만들어서 사용하는데

기본적으로 프록시란 @Transactional이 있는 어노테이션이 스프링빈으로 등록될 경우
트랜잭션이 걸려있는 클래스와 똑같은 클래스를 하나 더 만든다.
이 프록시 클래스는 타겟이 될 클래스(트랜잭션이 걸려있는 클래스)뒤에 $$CGLIB라는 이름이 붙는다.
예를들어 나는 ItemService란 클래스에 @Transactional붙이고
스프링 빈에 등록한다면
이 스프링빈은 ItemService란 프록시 클래스를 만들고
이 프록시 클래스의 이름은 ItemService$$CGLIB가 된다.
그리고 우리가 스프링빈에 등록되어있는(트랜잭션)이 있는 클래스를 호출하는 경우
스프링에 등록된 클래스를 호출 하는것이 아닌 프록시 클래스를 가져온다
그렇다면 이 프록시는 왜 필요한걸까??
[🍊트랜잭션의 프록시]
기본적으로 트랜잭션을 수행할 때 트랜잭션은 프록시를 기반으로 트랜잭션을 실행한다.
예를들어 나는 ItemService라는 클래스가 있다고 치자.
이 ItemSerivce에 트랜잭션이 붙었다면 이 ItemService는 스프링빈에 등록될 경우
프록시를 만들어낸다.
스프링은 이 프록시를 기반으로 트랜잭션을 실행하게 된다.

사진으로 한번 이해해보자.
txBasic이라는 클래스가 있다.
이 클래스가 트랜잭션이 있다면 txBasicTest$$CGBIB 라는 프록시가 스프링 빈에 등록된다.
그리고 우리가 스프링빈에 등록된 클래스를 호출하려할때
트랜잭션이 이 클래스에 있다면
txBasicTest$$CGBIB라는 프록시 클래스를 주고
트랜잭션이 없다면 이 클래스는 스프링이 제공하는 일반 클래스인 싱글톤으로 작동된다.
[예제]
아직말로해선 햇갈린다.
코드로 한번 봐보자.

일단 비지니스 클래스에는 DB에 저장만 하는 메서드인 save만 있다.
@Service를 붙였기 때문에 자동으로 스프링빈에 등록이 된다.
그리고 가장 중요한 것은 클래스나 메서드에 @Transactional이 하나라도 붙는다면
트랜잭션 AOP는 프록시를 만들어 스프링 컨테이너의 등록하게 된다.
이 서비스 클래스가 스프링빈에 등록되는 순간 프록시가 만들어 지는 것 이다.
한번 코드로 봐보자.

테스트 코드에는 ItemService를 찍는 로그를 만들었다.
이 로그를 확인해본다면

이런식으로 아이템서비스 뒤에 이상한 영어가 붙은것이 바로 프록시 이다.
메서드에 트랜잭션이 적용되었기 때문에 스프링에 등록되는 순간 프록시가 적용된 것 이다.
만약 서비스 클래스에 트랜잭션을 뺀다면 어떻게 될까?

나는 서비스 코드에서 트랜잭션을 빼고 테스트 코드를 실행시켰다.

트랜잭션을 빼고 실행시키니 이렇게 프록시가 빠진 원래 클래스가 찍히는걸 볼 수 있다.
이렇듯 트랜잭션은 이 프록시라는 기반으로 트랜잭션이 작용하는 것 이다.
한번 트랜잭션도 적용되는지 확인 해보자.

만약 아이템 이름에 트랜잭션 확인 이라는 문자가 들어오면 오류가 Runtime예외가 뜨게 만들어놨다.

테스트 코드를 본다면
메서드 한개는 정상적으로 이름에 아이패드를 넣어 정상동작되게 했고
두번 째 메서드는 아이템 이름에 트랜잭션 확인 라고 만들어 일부로 런타임 예외를 터뜨리게 했다.
그렇다면 DB에는 어떻게 저장될까?

이렇게 트랜잭션이 정상적으로 작동되는걸 볼 수 있다.
트랜잭션이 프록시를 도입하는 순간 정확히 어떻게 되는걸까?
한번 알아보자.

트랜잭션은 프록시를 도입하는 순간 이런 과정이 생긴다.
1. 클라이언트(사용자)가 호출을 하면 프록시가 시작된다.
2. 트랜잭션은 (항상) 트랜잭션 매니저를 통해서 동작하게 된다.
3. 트랜잭션은 프록시를 통해 트랜잭션 매니저를 들어간다.
4. 들어간 트랜잭션 매니저는 내부에서 데이터 소스를 찾아서 가져온다.
(매우 중요)
5. 찾은 데이터 소스(커넥션)을 트랜잭션 동기화 매니저에 보관해둔다.
(매우 중요)
6. 그 후 DB에 접근하는 로직이 트랜잭션 매니저가 저장해둔 데이터 소스를트랜잭션 동기화 매니저에 찾아 DB와 연결한다.
▶즉 DB가 트랜잭션 동기화 매니저에 있는 데이터 소스를 가져오기 때문에 반드시
트랜잭션 데이터 소스와 DB가 사용하는 데이터 소스가 같아야한다.
[정리]
트랜잭션은 동작하기 위해서는 프록시란 기술이 필요하다.
이 프록시란 기술은 트랜잭션이 동작하기 위해서 꼭 필요한 기술이다.
프록시는 트랜잭션이 걸린 클래스나 메서드가 하나라도 있고
클래스를 스프링빈에 등록되면 스프링빈은 프록시란 클래스를 스프링 빈에 등록한다.
등록된 프록시는 트랜잭션이 시작될 때 스프링은 기본 클래스를 주는 것이 아닌
프록시가 적용된 클래스를 적용하며 트랜잭션은 프록시 클래스를 기반으로
일련의 과정들을 거친다.
또한 프록시는 클래스나 메서드가 트랜잭션이 붙은 클래스를 타겟으로 삼아
프록시로 만든다.
'[스프링 DB] > 트랜잭션' 카테고리의 다른 글
[스프링 DB] 트랜잭션이 적용 안됨, 트랜잭션 주의 사항 (1) | 2023.06.28 |
---|---|
[자바 스프링] Test 에서의 트랜잭션 사용 (0) | 2023.06.20 |
[스프링] 트랜잭션의 이해와 활용,@Transactional 원리 - 기록만이 살길 (0) | 2023.06.14 |
[트랜잭션 이란 무엇인가?] - 트랜잭션의 이해 (2) | 2023.06.08 |
[스프링 오류]Could not initialize plugin: interface org.mockito.plugins.MockMaker (alternate: null) 설정오류 (0) | 2023.06.08 |