기존 전통적인 스프링 방식 개선
기존의 전통적인 스프링 방식은 컨트롤러가 종료되고 response를 해주기 직전에 JDBC 커넥션과 트랜잭션, 영속성 컨텍스트를 종료해주었다. 그런데 굳이 그렇게 하지 않고 서비스가 종료되고 나서 해주면 종료 시점이 당겨지기 때문에 DB의 부하가 적어진다. 모든 로직은 서비스에서 실행되기 때문에 당겨도 문제없다.
또한 JDBC 커넥션과 트랜잭션을 기존에는 요청이 들어오면 바로 시작했는데 컨트롤에서 사용할 일이 없으므로 요청이 들어오면 영속성 컨텍스트만 먼저 시작하고 JDBC 커넥션과 트랜잭션은 컨트롤러에서 서비스 단계로 넘어갈 때 시작시킨다. 이렇게 또 DB의 부하를 줄여준다.
그런데 만약 DB의 테이블이 Many To One 관계일 경우를 생각해보자
한 Team에 여러 Player들이 속할 수 있으므로 Many To One 관계이다. Many To One의 경우 기본 전략이 Eager이다.
@ManyToOne(fetch = FetchType.EAGER)
Eager은 관련된 정보까지 다 긁어오기 때문에 페이커를 select했을 경우 영속성 컨텍스트에 페이커와 페이커의 팀인 T1의 정보를 객체로 등록시킨다.
페이커의 정보만 필요한 상태니까 영속성 컨텍스트에서 repository로 두개의 정보 중 페이커의 정보만 가져온다. ORM이기 때문에 페이커 정보 안에 어짜피 Team 정보가 들어있다. 페이커 선수의 정보를 돌려주고 모든 걸 종료시키면 영속성 컨텍스트도 종료되면서 그 안의 정보들은 비영속 상태가 되어서 쓸모없게 된다.
Eager 전략이 아닌 Lazy 로딩할 수 있도록 Lazy 전략으로 바꿀 수 있다.
@ManyToOne(fetch = FetchType.LAZY)
Lazy 전략으로 변경할 경우 Lazy는 지연 로딩이라서 필요한 정보가 생기면 그때 요청하는 전략이다.
페이커 정보를 요청했을 때 페이커 정보만 가져오고 T1 정보는 안들고 온다. 그냥 비어있는 가짜 T1 프록시 객체를 들고와서 연결만 시켜둔다. DB select할 때 JOIN을 안해서 들고 온다는 뜻이니까 들고온 페이커 정보에 T1 정보가 포함되어 있지 않다. 이러고 나서 Controller에서 View를 생성해서 response해줄 때 화면에 데이터들을 보여줘야 할 때 JDBC, 트랜잭션, 영속성 컨텍스트 모두 종료된 상태에서 페이커 정보 뿐만 아니라 T1 정보까지 필요할 경우 T1 정보를 호출할 방법이 없다.
페이커 정보를 통해 T1 팀 정보를 호출하려면 영속성 컨텍스트가 종료되면 안된다. 그래서 영속성컨텍스트 종료 시점을 컨트롤러 작업이 끝난 후로 미룬다. 이러면 Controller에서 T1 정보가 필요해서 연결되어 있는 팀 프록시 객체를 호출하게 되면 영속성 컨텍스트의 T1 프록시 객체를 호출하게 되는데 이 때 JDBC 커넥션만 다시 시작시킨다. 실제 T1 팀 정보를 가져온 후 JDBC 커넥션을 다시 닫는다. 그러면 프록시 객체는 실제 T1 팀 객체가 되는 것이다.
이렇게 하면 필요시에 컨트롤러에서 연결된 정보를 select할 수 있다. 다만 DB 커넥션과 트랜잭션이 종료된 상태이므로 update는 불가능하다.
yml에서 jpa의 open-in-view를 true로 설정해주면 lazy-loading이 가능해진다.
그 이유는 영속성을 프리젠테이션 계층까지 가져가기 때문이다. 트랜잭션은 Service 계층에서 종료되는데 Controller의 Session이 close되지 않았기 때문에 영속 객체는 Persistence 상태를 유지할 수 있고, 프록시 객체에 대한 Lazy Loading을 수행할 수 있게 된다.
스프링 부트는 기본적으로 OSIV가 ture로 되어 있는데 이 때, 경고를 발행하므로 프로덕션 시스템에 영향을 주기 전에 이 문제를 발견할 수 있다.
정리
- 세션(영속성 컨텍스트 포함)의 시작은 서블릿이 시작되는 시점부터!!
- 트랜잭션과 JDBC의 커넥션, 종료는 Service 계층에서!!
- 세션은 컨트롤러 영역까지 끌고 가기 때문에 영속성이 보장되어 select가 가능해지고 lazy-loading이 가능해진다!!
출처 : https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9
'Spring > Blog 만들기 with SpringBoot' 카테고리의 다른 글
스프링부트 Spring Security (0) | 2022.07.14 |
---|---|
전통적인 방식의 로그인 (0) | 2022.07.09 |
DB 격리수준, 스프링의 트랜잭션 (0) | 2022.07.09 |
메인화면 구성 (0) | 2022.07.02 |
스프링 기본 파싱 전략과 JSON 통신 (0) | 2022.06.13 |