TIL/Spring

[SIST] Spring_days07_스프링 트랜잭션 전파방식(propagation)

야리니 2022. 7. 19. 22:12
728x90
반응형

1. 스프링에서의 전파방식이란?

- 트랜잭션 처리 과정 속에서 또 다른 트랜잭션을 처리해야 할 경우에는 어떻게 처리할 것인지 결정해 주는 것이 전파방식(propagation)이다.

위와 같이 중첩이 되는 트랜잭션 처리를 하나가 롤백이 되면 다른 하나는 롤백을 할 것인지 커밋을 할 것인지 등을 결정해준다.


2. 트랜잭션 전파와 관련해서 스프링이 지원하는 속성

트랜잭션 전파방식 설명
REQUIRED(기본값) 메서드를 수행하는데 트랜잭션이 필요하다는 것을 의미.
현재 진행 중인 트랜잭션이 존재하면, 해당 트랜잭션을 사용한다.(그 트랜잭션에 같이 묶임)
존재하지 않는다면 새로운 트랜잭션을 생성한다.
REQUIRES_NEW 항상 새로운 트랜잭션을 시작한다.
기존 트랜잭션이 존재하면 기존 트랜잭션을 일시중지하고 새로운 트랜잭션을 시작한다.
새로 시작된 트랜잭션이 종료된 뒤에 기존 트랜잭션이 계속된다.
MANDATORY 메서드를 수행하는 데 트랜잭션이 필요하다는 것을 의미
REQUIRED와 달리 진행 중인 트랜잭션이 존재하지 않을 경우 익셉션을 발생 시킴
SUPPORTS 메서드가 트랜잭션을 필요로 하지는 않지만, 기존 트랜잭션이 존재할 경우 트랜잭션을 사용한다는 것을 의미
진행 중인 트랜잭션이 존재하지 않더라도 메서드는 정상적으로 동작
NOT_SUPPORTS 메서드가 트랜잭션을 필요로 하지 않음을 의미
SUPPORTS와 달리 진행 중인 트랜잭션이 존재할 경우 메서드가 실행되는 동안 트랜잭션은 일시 중지되며, 메서드 실행이 종료된 후에 트랜잭션을 계속 진행
NEVER 메서드가 트랜잭션을 필요로 하지 않으며, 만약 진행 중인 트랜잭션이 존재하면 익셉션을 발생 시킴
NESTED 기존 트랜잭션이 존재하면, 기존 트랜잭션에 중첩된 트랜잭션에서 메서드를 실행
기존 트랜잭션이 존재하지 않으면 REQUIRED와 동일하게 동작
이 기능은 JDBC 3.0 드라이버를 사용할 때에만 적용(JTA Provider가 이 기능을 지원할 경우에도 사용 가능)

3. 전파방식 예제

예제를 다루기 전 DB 상황을 먼저 파악해보면, notices 테이블은 제목이 중복될 수 없는 유니크 제약조건을 주었고 member 테이블은 한 회원이 point가 3 이상일 수 없는 체크 제약 조건을 주었다.

(포인트는 공지사항을 쓰면 +1 되는 update를 실행)

 

스프링 설정은

dispatcher-service.xml 파일과 dispatcher-servlet.xml 파일이 부모-자식 계층으로 설정

컴포넌트 스캔 기능을 사용하며, dispatcher-service.xml에서 트랜잭션 매니저 등록

dispatcher-servlet.xml에서 @Transactional 애노테이션을 사용한 트랜잭션 처리 설정을 해준 상태

 

각각의 테스트를 할 때에는 회원의 포인트를 1로 설정한 후 커밋 작업을 해주자!


(1) 중첩 트랜잭션 처리시 각 메서드에 @Transactional(propagation = Propagation.REQUIRED) 설정

트랜잭션이 걸려져 있는 메서드 안에서 트랜잭션이 걸려져 있는 또 다른 메서드를 호출하는 환경으로 설정 후 실습을 해보는 예제이다.

 

[NoticeDao 인터페이스]

 

[NLNoticeDao 클래스]

- 트랜잭션 처리를 하는 insertAndPointUpOfMember() 메서드 안에서 트랜잭션 처리를 하는 insert() 메서드를 호출하는 상황

 

> insert() 메서드

> insertAndPointUpOfMember() 메서드

 

[CustomerController 클래스]

> noticeReg() 메서드

 

[테스트]

 

회원의 포인트가 1인 상황에서 공지사항 작성을 하면..

TEST 1 공지사항 작성 회원의 포인트 1증가(2) -> 롤백

TEST 1-2 공지사항 작성 회원의 포인트 1증가(3) -> 롤백

하나의 트랜잭션에 묶여져 있기 때문에 모두 롤백이 되어진다.(REQUIRED로 현재 진행 중인(insertAndPointUpOfMember() 메서드) 트랜잭션을 사용)

즉, 공지사항도 작성이 안되고 포인트도 증가가 되지 않아 포인트는 1 값이 그대로이다.


(2)  insertAndPointUpMember() 메서드에서 @Transactional 애노테이션 없앤 후(insert 메서드에만 @Transactional 설정)

[NLNoticeDao 클래스]

 

[테스트]

회원의 포인트가 1인 상황에서 공지사항 작성을 하면..

TEST 1 공지사항 작성 회원의 포인트 1증가(2) -> 커밋

TEST 1-2 공지사항 작성 회원의 포인트 1증가(3) -> 공지사항 쓰기만 커밋 포인트 증가 롤백

 

insert() 메서드에만 @Transactional(REQUIRED) 되어 있어서 트랜잭션 처리가 제대로 되지 않았다.

이유는 AOP 방식의 트랜잭션 처리 때문이라고 하셨는데 자세한 설명은 해주지 않으셨다.

검색해보았는데..

트랜잭션은 객체 외부에서 처음 진입하는 메서드를 기준으로 동작한다.

AOP는 흩어진 관심사를 별도의 클래스로 모듈화하는 프로그래밍 방법을 말하며, OOP를 더욱 잘 지킬 수 있도록 도움을 준다.

Spring AOP는 프록시 객체를 자동으로 생성해주어, Aspect/Advice에 직접적으로 의존하지 않게 해준다.

참고 : https://velog.io/@ann0905/AOP%EC%99%80-Transactional%EC%9D%98-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC

 

위와 같은 문제를 해결하기 위해서는 두 개의 메서드가 다른 클래스에 있도록 분리시켜를 주어야 한다.

해결하는 예제는 (3)에서 다루겠다.


(3) 2번 예제에서 발생한 문제를 해결하기 위해서 insertAndPointUpMember()와 insert() 메서드를 다른 클래스에 있도록 클래스를 분리

newlecture.service 패키지 생성
   ㄴ MemberShpService 인터페이스 생성
   ㄴ NLMemberShipService 클래스 생성


NoticeDao 인터페이스에서 insertAndPointUpOfMember 메서드를 분리하여 MemberShpService 선언
insertAndPointUpMember() 메서드를 분리 하고 @Transactional(REQUIRED) 애노테이션은 추가하지 않은 상태이며, insert() 메서드에만 @Transactional(REQUIRED) 추가되어졌다.

 

[NLNoticeDao 클래스]

 

[MemberShpService 인터페이스]

 

[NLMemberShipService 클래스]

 

[CustomerController 클래스]

 

[테스트]

 

회원의 포인트가 1인 상황에서 공지사항 작성을 하면..

TEST 2 공지사항 작성 회원의 포인트 1증가(2) -> 커밋

TEST 2-2 공지사항 작성 회원의 포인트 1증가(3) -> 롤백

insert() 메서드에만 @Transactional(REQUIRED)를 설정해 주었기 때문에 하나의 insert() 메서드에 대해서 트랜잭션 처리를 한다.


(4) insertAndPointUpMember()와 insert() 메서드에 @Transactional(REQUIRED) 추가

이번에는 MemberShipService 인터페이스에 @Transactional(REQUIRED) 애노테이션을 선언하여 해당 인터페이스에 있는 모든 메서드를 트랜잭션 처리를 하겠다고 설정하겠다.

 

[테스트]

회원의 포인트가 1인 상황에서 공지사항 작성을 하면..

TEST 3 공지사항 작성 회원의 포인트 1증가(2) -> 롤백

TEST 3-2 공지사항 작성 회원의 포인트 1증가(3) -> 롤백

모두 롤백 되어진다.

즉, REQUIRED로 인해서 현재 진행 중인 트랜잭션(insertAndPointUpOfMember 메서드)에 합류했기 때문에 모두 롤백되어졌다.


(5) insert() 메서드의 @Transactional을 REQUIRES_NEW로 변경

REQUIRES_NEW는 항상 새로운 트랜잭션으로 진행(종료된 두 기존 트랜잭션 계속)

 

[NLNoticeDao 클래스]

 

[테스트]

 

회원의 포인트가 1인 상황에서 공지사항 작성을 하면..

TEST 4 공지사항 작성 회원의 포인트 1증가(2) -> 커밋

TEST 4-2 공지사항 작성 회원의 포인트 1증가(3) -> 롤백

728x90
반응형