카테고리 없음

JPA OSIV(Open Session In View), Fetch의 EAGER전략과 LAZY전략, 스프링부트 yml파일 open-in-view:true

shika 2022. 5. 4. 20:04

먼저 JPA의 Fetch 전략에 대해서 살펴보자면

EAGER전략과 LAZY 전략이 있다.

 

EAGER은 즉시 로딩

LAZY는 지연 로딩이라고 보면 된다.

 

이게 그럼 무엇이냐?

 

DB에 야구선수가 있고

야구선수 테이블은 fk로 해당 선수의팀 테이블을 가지고 있다고 생각해보자

 

JPA를 사용시에 간단히

EAGER 전략은 

사용자가 선수객체에 대한 정보를 요청했을때(선수를 불러오려고 DB에서 쿼리날릴때)

바로 팀 객체 정보까지 불러오는 것이다

편하지만 많은 정보를 불러오므로 속도가 느릴 수 있다.

 

LAZY 전략은

사용자가 선수정보를 요청했을 때(팀 객체는 비어있는 가짜객체를 생성해놓고)

진짜 팀 객체가 필요할때만

팀 객체를 불러오는 것이다.

이건 빠르지만 무조건 딸려온 정보를 다 불러와야 될때는

위에것보다는 안 좋을 것이다.

 

 

일단 이걸 알고 바로 밑의 그림을 보면서 더 자세하게 이해해보자

 

먼저

사용자가 request를 하면 session이 열린다.

세션 시작 --> 영속성 컨텍스트가 시작되었다 (세션안에 영속성 컨텍스트 존재)

request가 일어나면 controller 진입 직전에 서블릿 필터에서 영속성 컨텍스트가 시작되고

1차 캐시 또한 만들어진다.

그리고 컨트롤러로 요청이 가고 

컨트롤러가 서비스에 요청을 할때 JDBC 커넥션이 만들어지고

트랜잭션 또한 시작된다.

 

그 후 서비스에서 레파지토리로 요청이 가고 쭉쭉 진행되는데

그 후 1차 캐시에 데이터 없으면 DB까지 들어가서 정보를 가져온다.

그 때 1차 캐시에 객체가 만들어지는데

이때 내가 요청한 하나의 객체가 만들어지고

그 객체가 연결되어 있는 

(예를 들어 선수 객체를 가져오는데 fk로 팀 객체를 가지고있다면)

팀 객체를 가져올 때 

 

EAGER 전략이라면 

팀 객체를 바로 들고 오겠지만

EAGER전략이 아니라 LAZY 전략이라면

팀 객체를 바로 들고오는 것이 아닌 팀 객체에 대한 프록시 객체를 가져오게 된다

(프록시 객체란 비어있는 이름만 있는 객체라고 생각하자

나중에 필요하면 사용하고 필요하지 않으면 사용하지 않기 위해서 임시로 만드는 가짜객체

라고 이해해보자)

 

그리고 영속성 컨텍스트에서 다시 레파지토리로 정보를 주고

서비스로 가서 업데이트나 인서트나

어떠한 활동을 한뒤에

JDBC 커넥션과 트랜잭션이 종료된다!!

 

여기서 중요한점 (아직 서비스만 끝나고 컨트롤러로 가기 전임)

바로 영속성 컨텍스트는 살아있다는 것이다.

 

그래서 컨트롤러에서 팀 객체를 가져오고 싶다?

(이해가 쉽게 팀 객체라고 한것, 한마디로 내가 가져온 객체와 연결된 fk객체라고 생각하자)

그러면 팀 프록시 객체가 진짜 팀 객체로 변경이 된다

(비어있었지만 아직 영속성 컨텍스트와 연결되어있으므로 비어있는 객체에 내용이 들어가는것)

 

그말은 다시 데이터베이스를 열어 JDBC 커넥션에 잠깐 연결이 가능하다는 뜻이다.

이 때 또 중요한것은!!

트랜잭션은 다시 시작되는것이 아니기 때문에

업데이트나 인서트는 못한다 (commit 관련된건 싹다 못함 / 유일하게 select만 가능)

유일하게 영속성 컨텍스트와 연결되어있기 때문에

fk로 연결되 정보만 들고올 수 있는 것이다.

 

결론은 그래서 팀 프록시 객체 (가짜 객체)가

팀 객체(진짜 객체)로 바뀌고

그게 응답이 되는 것이다.

 

그러면 사용자는 선수객체와 팀 객체를 모두 얻게 되는것이다.

 

전통적인 방식에서는 request가 시작할 때

jdbc, 트랜잭션, 영속성 컨텍스트가 다시작되고

응답을 거쳐 컨트롤러가 끝나는 시점에 3개가 동시에 종료되는것과는

굉장한 차이가 존재한다.

 

스프링 2.0부터는 전통적 방식보다 위에서 언급한 OSIV전략이

기본적으로 실행된다.

 

기본적으로 application.yml에서  값을 안줘도  open-in-view:true 이고

이걸 끄고 싶다면 true를 false 로 바꿔주면 된다.

 

다른 블로그에서 보니

기본적으로 LAZY전략을 사용하고 꼭 필요할때만

EAGER전략을 사용하는 것이 좋다고 한다.

 

LAZY가 뭔가 만능인 느낌적인 느낌이 든다.