Java/JPA

즉시 로딩과 지연 로딩

Lea Hwang 2022. 5. 25. 14:07

프록시 포스팅에 이어서 즉시 로딩과 지연 로딩의 주제로 넘어가 보겠습니다.

 

 

지연 로딩 LAZY를 사용해 프록시로 조회

@Entity
public class Member{
	...
	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "TEAM_ID")
	private Team team;
	...
}

 

  • member 조회 시 (team을 Join하지 않고) member만 조회 쿼리 나가고
    • team 객체는 Proxy 객체로 생성됨.
  • 이후실제로 team을 사용하는 시점에 초기화(DB 조회) 되면서 쿼리 나감

 

 

만약 Member와 Team을 자주 함께 사용한다면,

 

즉시 로딩 EAGER를 사용해 함께 조회

@Entity
public class Member {
	...
	@ManyToOne(fetch = FetchType.EAGER)
	@JoinColumn(name = "TEAM_ID")
	private Team team;
	...
}
  • 위 Annotation 적용 시, member를 조회할 때 항상 team을 함께 조회함.
    • JPA 구현체는 가능하면 조인을 사용해서 SQL 한 번에 함께 조회

 

 

❗❗즉시 로딩 주의사항

1. (가급적) 지연 로딩만 사용 (특히 실무에서)

  • Join이 늘어나면 수많은 테이블을 쿼리 할 수도 있음.

2. 즉시 로딩 적용 시 예상치 못한 SQL이 발생

  • 💡 JPQL로 “SELECT m from Member m” 쿼리를 전송하면, Join 된 테이블도 중첩되어 조회함.

3.💡 @ManyToOne, @OneToOne은 Default가 EAGER이므로, LAZY로 수정

 

4. @OneToMany, @ManyToMany는 Default가 LAZY

 

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

  • Member 조회 쿼리를 JPQL로 짰을 때, JPQL은 SQL로 번역되고 Member조회 쿼리 가져옴 (1개)
  • 그 후 즉시 로딩 설정한 것이 확인되면, Member의 수(N) 만큼 Join 된 테이블(Team) 조회하는 별도 쿼리 나감(N개)
  • 기본적인 해결 방법
    • 모든 연관관계를 지연 로딩으로 바꾼 후
    • JPQL Fetch 조인
List<Member> members = em.createQuery("select m from Member m join fetch m.team", Member.class)
				.getResultList();

 

 

지연 로딩 활용

1. “이론적으로는” 아래와 같이 사용하나, 실무에서는 모두 지연 로딩을 권장

 

2. 실무에서 즉시 로딩을 사용하지 말 것! 즉시 로딩은 상상하지 못한 쿼리가 나간다.

  • 필요한 경우 JPQL Fetch 조인이나 Entity 그래프 기능을 사용

 

 


 

 

JPA기본편 스터디 함께한 Jarry, Matt 항상 감사합니다.

 

 

참고 :

https://www.inflearn.com/course/ORM-JPA-Basic

 

자바 ORM 표준 JPA 프로그래밍 - 기본편 - 인프런 | 강의

JPA를 처음 접하거나, 실무에서 JPA를 사용하지만 기본 이론이 부족하신 분들이 JPA의 기본 이론을 탄탄하게 학습해서 초보자도 실무에서 자신있게 JPA를 사용할 수 있습니다., - 강의 소개 | 인프런

www.inflearn.com