스프링의 전통적인 트랜잭션 방식과 이에 대한 문제점, 개선까지

myeonji·2022년 2월 18일
1

스프링의 시작

  1. 톰캣 시작 (서버작동)
  2. web.xml 읽기
  3. context 읽기
  4. DB 연결 테스트

시작 (전통적 방식)

  1. 사용자의 request : 송금 요청 (A->B에게 10000원 송금)

  2. web.xml 거치고 필터를 거쳐서 Controller로 옴

  3. web.xml 거치고 필터 거치는 시점에

  • (1) DB 연결 세션 생성 -> JDBC 커넥션 연결 됨
  • (2) 트랜잭션 시작
  • (3) 영속성 컨텍스트 시작
  1. Controller에서 요청분기

  2. 요청에 맞는 Service 호출

  3. 송금() 메소드 실행

💡 여기서 송금을 위한 update 수행 방식 : 두 계좌를 select 해서 Service에서 처리 후 save() 없이 변경감지로 DB에 flush 되는 방식인 더티체킹 사용

  1. A와 B select 해서 DB에서 가져와 영속성 컨텍스트에 두 계좌 객체화 시킴

  2. select된 객체를 영속성 컨텍스트에서부터 받아와서 Service에서 값 변경 (처리) (값 변경 : A는 -10000원, B는 +10000원)

💡 현재 DB에 반영된 것이 아니라 영속성 컨텍스트에 있는 객체의 값만 변경된 상태

💡 Service -> Controller 끝난 후 아래 단계 수행
BUT, 시점을 줄여서 Service까지만 종료된 후 아래 단계 수행해도 됨 -> 데이터베이스 커넥션 시점이 줄고, 트랜잭션 범위 줄고, 영속성 컨텍스트도 빨리 종료되어 DB 부하 적어짐

  1. 응답 전에 JDBC 커넥션 종료

  2. 트랜잭션 종료 -> commit -> 변경감지 -> flush 되어 DB에 반영 (update 수행)

  3. 영속성 컨텍스트 종료

  4. Controller에서 사용자에게 response(응답)

  • RestController : Data (JSON)
  • Controller : .html

시점 늦추고 당기기

전통적인 방식으로는 영속성 컨텍스트와 트랜잭션, JDBC 커넥션 세 개가 같이 시작되고 종료되었다. (OPEN SESSION IN VIEW 패턴)

하지만, SpringMVC에서 제공하는 OpenSessionViewFilter는 필터 내에서 Session은 오픈하지만 트랜잭션은 시작하지 않는다.

시점 늦추기

  • Controller 지나고 Service 직전에 실행되어도 됨.

(1) DB 연결 세션 생성 -> JDBC 커넥션 연결 시작
(2) 트랜잭션 시작

시점 당기기

  • Service만 끝나고 종료되어도 됨.

(4) JDBC 커넥션 종료
(5) 트랜잭션 종료 -> commit -> 변경감지 -> DB에 반영 (update 수행)
(6) 영속성 컨텍스트 종료


스프링 JPA의 OSIV 전략

하지만, 영속성 컨텍스트의 시작은 Controller 직전, 종료는 Controller까지 지난 후에 이루어져야 한다.
그래야 LAZY 로딩을 사용할 수 있다.


이렇게 open-in-view 를 true 로 설정하면 LAZY 로딩이 가능하다. (기본 true)
영속성 컨텍스트의 시작과 종료가 각각 Controller 시작 전, Controller까지 끝난 후에 이루어 져야 한다.

  • 만약 false로 한다면 영속성 컨텍스트 시작 시점이 Contorller와 Service 사이로 내려오고, 종료 시점 또한 Service와 Controller 사이로 된다. 따라서 영속성 컨텍스트가 Service가 끝나고 종료된다면 Controller에서 불러오려고 해도 영속성 컨텍스트가 닫혀있기 때문에 불러오지 못한다.

참고
참고

0개의 댓글