Malachai Lee 2022. 4. 24. 19:24

스프링의 전통적인 트랜잭션

 

 

스프링의 동작원리

스프링은 내장 톰캣을 가진다 2022.04.12 - [Today I Learned/개념 정리] - 소켓 소켓 소켓은 운영체제가 가지고 있는 물리적으로 연결되어있는 네트워크상의 다른 기계나 애플리케이션간 데이터 송수신

malachai.tistory.com

 

스프링 서버 구동: 톰캣 시작 → 서버 작동 → web.xml 확인 → context.xml 확인, DB연결 테스트

요청 처리 순서

① 송금 요청 수신

② 요청이 web.xml을 거치며 DB 연결 세션 생성

③ 요청이 필터를 거치며 JDBC 커넥션 시작 → 트랜잭션 시작 → 영속성 컨텍스트 시작

④ 요청 분기를 확인 후, 요청에 맞는 서비스 호출

⑤ 송금 서비스가 홍길동 SELECT, 장보고 SELECT

⑥ 영속성 컨텍스트에 객체 생성(1차 캐시에 엔티티 생성)

⑦ Repository를 통해 데이터를 들고와 값을 변경

⑧ 업데이트 결과 반환

⑨ JDBC 커넥션 종료 → 트랜잭션 종료(commit → 영속성 컨텍스트 변경감지, 데이터가 바뀌었다면 flush) → 영속성 컨텍스트 종료 → 응답 반환(Controller라면 html, RestController라면 데이터 반환) → DB연결 세션 종료

 

 

기존 스프링의 트랜잭션 개선과 JPA의 OSIV 전략

스프링부트는 자원 소모 감축을 위해 두가지 과정을 수정하였다.

  1. 응답과정⑨에서 JDBC, 트랜잭션, 영속성 컨텍스트를 종료시키는것 보다 Service-Controller과정⑧에서 종료시키는것이 더욱 효율적 - DB 커넥션 시간과 영속성 컨텍스트 지속시간이 줄고 트랜잭션 범위가 적어진다.
  2. 필터를 거치며③ JDBC, 트랜잭션을 시작하는것 보다 Controller-Service과정④에서 시작하는것이 더욱 효율적 - DB 커넥션 시간과 영속성 컨텍스트 지속시간이 줄고 트랜잭션 범위가 적어진다.

 여기서 문제점이 생기는데, 가져온 엔티티가 FK를 가지고, FetchType.LAZY의 경우일때이다. 기본적으로 지연로딩을 사용하며 DB에서 영속성 컨텍스트로 값을 가져올땐 연관객체가 실제 DB에서 가져온 데이터가 아닌 프록시, 비유하자면 빈 객체의 형태로 붙게 된다. 컨트롤러가 연관객체를 사용할것인지 모르기 때문에 “필요하다면 로딩” 전략이 지연로딩의 전략이다.

 컨트롤러가 연관객체를 필요로 한다면, 개선안에의 컨트롤러에서는 영속성 컨텍스트가 이미 종료된 다음 시점이다. 따라서 프록시 객체를 호출해도, 컨텍스트 내의 프록시는 다시 볼 수 없게 된다. 이 말인 즉슨, 지연로딩을 사용할 수 없게 된다.

 이를 개선하여 영속성 컨텍스트의 시작과 종료만을 서블릿 필터로 당기는것이다. 이 전략을 OSIV(Open Session In View)이라고 부른다. 컨트롤러에서 지연로딩으로 연관객체를 사용하면, 영속성 컨텍스트 내부의 프록시가 호출이 되고 연결이 끊어졌던 JDBC를 다시 연결하여 정보를 들고온 후 곧바로 연결을 끊는다. 이 과정은 물론 SELECT로직만 가능하다.(read-only)

 

스프링부트의 트랜잭션 - JPA OSIV 전략

스프링 서버 구동: 톰캣 시작 → 서버 작동 → web.xml 확인 → context.xml 확인, DB연결 테스트

요청 처리 순서

① 송금 요청 수신

② 요청이 web.xml을 거치며 DB 연결 세션 생성

③ 요청이 필터를 거치며 영속성 컨텍스트 시작

④ 요청 분기를 확인 후, 요청에 맞는 서비스 호출, JDBC 커넥션 시작 → 트랜잭션 시작

⑤ 송금 서비스가 홍길동 SELECT, 장보고 SELECT

⑥ 영속성 컨텍스트에 객체 생성(1차 캐시에 엔티티 생성)

⑦ Repository를 통해 데이터를 들고와 값을 변경

⑧ 업데이트 결과 반환, JDBC 커넥션 종료 → 트랜잭션 종료(commit → 영속성 컨텍스트 변경감지, 데이터가 바뀌었다면 flush)

⑨ 영속성 컨텍스트 종료 → 응답 반환(Controller라면 html, RestController라면 데이터 반환) → DB연결 세션 종료

  • ⑧, ⑨의 사이에 Lazy Loading을 실행한다면, 프록시 접근 → JDBC 커넥션 연결 → 연관객체 SELECT, 데이터 반환 → JDBC 커넥션 종료

참고자료

 

[JPA] OSIV란? (feat. 스프링 JPA의 작동원리, 퍼사드 패턴 등)

OSIV에 다가가기까지 조금 서론이 길다. (JPA의 작동원리, FACADE 계층 등) OSIV에 대해서만 궁금하다면 그쪽 부분만 찾아서 보길 바란다. 스프링에서 JPA를 사용하게 되면, 스프링 컨테이너가 트랜잭

ttl-blog.tistory.com