본문 바로가기
JPA/JPA원리

19. 지연로딩

by 킹차니 2021. 7. 16.

 

김영한님의 인프런 강의와 PDF를 바탕으로 정리하였습니다.
https://www.inflearn.com/courses?s=%EA%B9%80%EC%98%81%ED%95%9C

즉시로딩과 지연로딩

 

프록시 포스팅에서 했던 질문입니다.

 

단순히 member 정보만 사용하는 비즈니스 로직일때 Member를 조회할 때 Team도 함께 조회해야 할까?

println(member.getName()); // 이렇게 member의 name만 필요한 경우 team까지 조회하는 것은 비효율적

 

프록시를 먼저 학습한 이유가 있는데, 지연로딩 LAZY를 사용해서 조회한다면 위와 같은 문제를 해결할 수 있습니다.

그런데 지연로딩에는 프록시가 적용됩니다.

 

 

 

지연로딩 LAZY

다음과 같이 Member엔티티의 @ManyToOne을 다음과 같이 수정합니다.

@ManyToOne(fetch = FetchType.LAZY)

위와 같이 하면 Member 객체의  team에 대해 지연로딩이 적용됩니다.

 

이렇게 한후 다음 코드를 수행하면

아래와 같은 결과가 나옵니다.

team에 대해 join하지 않은 select문이 나갑니다.

 

 

아래와 같이 team 객체를 만들어 team을 member에게 set하고 team의 class정보를 출력해보았습니다.

결과를 보면 team 객체가  프록시 객체로 나왔습니다.

 

현재 team은 프록시 객체이므로 아래와 같이 team에 대한 정보(아래에서는 name)를 건드리는 순간 select쿼리가 나갑니다.

member1.getTeam().getName();

을 했을 때 초기화가 되는 것입니다.

 

 

 

 

즉시로딩

 

그런데 어떤 비즈니스 로직에서는 Member와 Team을 거의 항상 같이 조회해서 위와 같이 따로 조회하면 성능상 손해인 경우가 있을 수 있습니다. 그래서 즉시 로딩을 사용할 수 있습니다.

 

@ManyToOne(fetch = FetchType.EAGER) 로 수정하면 됩니다.

 

그럼 아래와 같은 코드가 있을 시에

 

아래의 결과에서 보듯이 team까지 한번에 가져옵니다.(프록시를 사용하지 않음)

 

 

 

그런데 위와 같은 즉시 로딩은 사용하지 않는 것이 좋습니다.

 

 

 

프록시와 즉시로딩 주의

1. 실무에서는 즉시로딩 쓰지 말자! (지연로딩만 쓰자)

2. 즉시 로딩을 적용하면 예상하지 못한 SQL이 발생

3. 즉시 로딩은 JPQL에서 N+1 문제를 일으킨다.

4. @ManyToOne, @OneToOne 기본이 즉시 로딩
 -> LAZY로 설정

5. @OneToMany, @ManyToMany는 기본이 지연 로딩

(한방에 조회가 필요할 때는 패치조인을 사용한다.)

(실무에서는 모두 지연로딩으로 처리하자)

 

 

 

지연로딩 활용

 

1. Member와 Team, Member와 Order, Order와 Product 모두 지연로딩을 쓰자.

2. 모든 연관관계에 지연 로딩을 사용합시다! 즉시 로딩을 사용하시면 안됩니다!

3. JPQL fetch 조인이나, 엔티티 그래프 기능을 사용해라!
 (뒤에서 설명)

4. 즉시 로딩은 상상하지 못한 쿼리가 나간다.

'JPA > JPA원리' 카테고리의 다른 글

21. 실전예제 적용해보기  (0) 2021.07.16
20. 영속성 전이 : CASCADE, 고아객체  (0) 2021.07.16
18. 프록시  (0) 2021.07.15
17. @MappedSuperclass  (0) 2021.07.14
16 상속관계 매핑  (0) 2021.07.14