인프런 영문 브랜드 로고
인프런 영문 브랜드 로고

인프런 커뮤니티 질문&답변

양지웅님의 프로필 이미지
양지웅

작성한 질문수

실전! 스프링 부트와 JPA 활용2 - API 개발과 성능 최적화

간단한 주문 조회 V1: 엔티티를 직접 노출

강제 지연 로딩 초기화에 관한 질문입니다.

해결된 질문

작성

·

712

2

우선 2개의 질문을 참고하였습니다.

이것과

이것입니다.

 

두개의 글을 종합해 보면,

V1에서 Order리스트를 반환할때는 Lazy방식이기 때문에 Member객체가 프록시 객체이고, Jackson이 해당 해당 객체를 접근하는 순간 초기화한다는 것입니다. 그리고 해당 프록시 객체를 JSON으로 읽을수 있도록 도와주는 것이 하이버네이트5모듈이라는 것입니다.

 

여기서 궁금한 점이

//강제 지연 로딩 설정
hibernate5Module.configure(Hibernate5Module.Feature.FORCE_LAZY_LOADING, true);

이 코드입니다.

 

해당 코드는 강제 지연 로딩 설정이라고 하는데

강의 21분 20초경 LAZY를 강제 초기화 한다고 나와있습니다.

저는 위의 코드와

for (Order order : orders) {
    order.getMember().getName();
    order.getDelivery().getAddress();
}

이 코드가 같은 역할을 한다고 이해했습니다.

 

위의 두개의 코드를 삭제하면, 포스트맨으로 요청을 보냈을 때,

Member, orderItems, Delivery에는 null 값이 들어갑니다.

 

두개의 코드중 하나를 넣으면 요청을 넣었을때

Member, orderItems, Delivery에 실제 값이 들어가게 됩니다.

하지만 위의 두 글을 종합한 내용을 보면

Jackson이 해당 해당 객체를 접근하는 순간 초기화

라는 내용이 있습니다. 그렇다면 이미 초기화 된 프록시 객체일텐데 왜 위의 강제초기화 코드를 넣어야 실제 값이 들어가게 되는지 궁금합니다.

 

jackson이 프록시 객체에 접근할때 초기화가 되어서 두 코드를 넣지 않아도 null이 아닌 실제 값이 나와야하는 것 아닌가요?

 

 

글이 너무 길어 죄송합니다..ㅠㅠ

 

 

 

답변 1

2

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 양지웅님

FORCE_LAZY_LOADING 옵션이 적용되어 있으면 데이터가 나와야할 것 같아요.

실제 데이터가 없는 것은 아닐까요? 이부분을 먼저 확인해주세요.

만약 실제 데이터가 있다면

전체 프로젝트를 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.

구글 드라이브 업로드 방법은 다음을 참고해주세요.

https://bit.ly/3fX6ygx

주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요

추가로 다음 내용도 코멘트 부탁드립니다.

1. 실행 방법을 알려주세요.

2. 어떻게 문제를 확인할 수 있는지 자세한 설명을 남겨주세요.

감사합니다.

양지웅님의 프로필 이미지
양지웅
질문자

죄송합니다. 제가 글을 너무 두서 없이 적어버렸네요..

음.. 그러니까 제가 궁금한 점은

Jackson이 해당 해당 객체를 접근하는 순간 초기화해준다는 내용입니다..

Jackson이 자동으로 초기화를 해주는데 LAZY 강제 초기화 코드를 넣는 이유가 궁금합니다.!!

 

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 지웅님^^

질문하신 내용이 어떤 의도인지 이해가 되네요. 이 부분을 명확하게 이해하려면 활용 2편에서 OSIV에 대해서 학습해야 합니다.

우선은 제가 대략적으로만 설명드릴게요^^

지연로딩을 하려면 영속성 컨텍스트가 살아있어야 합니다.

JPA는 기본적으로 트랜잭션과 영속성 컨텍스트를 동기화 합니다. 쉽게 이야기해서 트랜잭션이 살아있어야 영속성 컨텍스트도 존재한다는 뜻이지요.

그런데 Jackson을 사용해서 API를 렌더링 하는 시점은 이미 트랜잭션이 끝난 시점입니다. 따라서 영속성 컨텍스트도 없기 때문에, null로 반환되거나, 또는 지연 로딩 실패 예외가 발생합니다.

이게 정상 동작하게 하려면 영속성 컨텍스트를 트랜잭션이 끝난 시점에도 살려두어야 하는데요. 결과적으로 OSIV라는 방법을 학습해야 합니다. (참고로 스프링 부트는 기본으로 OSIV를 활성화 해둡니다.)

OSIV와 관련된 부분은 활용2편에서 자세히 설명드립니다^^

감사합니다.

김영한님의 프로필 이미지
김영한
지식공유자

안녕하세요. 양지웅님

FORCE_LAZY_LOADING이 되어 있으면, 결과가 null이 아니라 데이터가 보이는 것이 맞습니다. (물론 데이터가 없다면 null입니다. 데이터가 있는지 확인해주세요.)

어떤 문제가 있어서 정상 동작하지 않는지 코드 확인이 필요합니다.

전체 프로젝트를 압축해서 구글 드라이브로 공유해서 링크를 남겨주세요.

구글 드라이브 업로드 방법은 다음을 참고해주세요.

https://bit.ly/3fX6ygx

주의: 업로드시 링크에 있는 권한 문제 꼭 확인해주세요

추가로 다음 내용도 코멘트 부탁드립니다.

1. 실행 방법을 알려주세요.

2. 어떻게 문제를 확인할 수 있는지 자세한 설명을 남겨주세요.

감사합니다.

양지웅님의 프로필 이미지
양지웅

작성한 질문수

질문하기