JPA 연관관계에서는 Fetch Type을 정해줄 수 있다.
Lazy, Eager 둘 중 하나를 선택할 수 있다.
무엇을 하는 설정이냐면,
JPA를 사용해서 엔티티를 조회해올 때 연관 관계의 엔티티들도 Select 해올 것인지 아니면 프록시 객체로 대체할 것인지를 정하는 것이다.
FetchType.LazySelect절로 조회해올 수 있다.FetchType.EagerJPA의 연관 관계는 Fetch Type의 관점에서 두 가지로 나눌 수 있다
~ToManyFetchType.Lazy가 기본 설정~ToOneFetchType.Eager가 기본 설정위와 같이 필요한 선행 지식을 간단하게 정리해봤다.
주변에서 JPA를 공부하고 사용하는 사람들을 보면 공통적으로 항상 연관 관계들의 Fetch Type을 Lazy로 명시한다.
만약 즉시 로딩을 한다면 필요 없는 순간에도 연관 관계에 대한 Select 문을 날리기 때문이다.
사실 지연 로딩만 쓰는 것이 가장 좋다면, 왜 JPA 개발자들은 ~ToOne 관계의 기본을 Eager로 했을까?
즉시 로딩이 좋은 경우가 있을 것이라고 가정하고 두 가지 상황을 살펴보자.
Team과 Member가 1:N의 연관 관계를 가진다
@Entity
public class Team {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@JoinColumn(name = "teamId")
@OneToMany(cascade = CascadeType.PERSIST)
private List<Member> members;
}
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
}
우선 기본 정책인 Lazy인 경우에서 팀을 조회해오고 게터로 멤버를 꺼내는 상황을 테스트 해본다.

위와 같이 추가적인 Select문이 실행된다.
Eager로 설정하고, 팀을 조회한 뒤 게터로 멤버를 꺼내는 상황을 테스트 해본다.

위와 같이 Outer Join으로 가져온다.
만약 Team을 사용할 때 항상 Member가 필요하다면 Eager 전략이 더 좋을 수도 있다고 생각한다.
다만 주의해야할 점으로는
위의 주의해야할 점을 모두 충족한다면 Eager가 더 나을 수도 있다.
하지만 충족한다고 생각하더라도 비즈니스 요구사항이 변경되면 바뀔 수 있다. 이 경우 Lazy로 바꾸고 관련 부분에 대한 N+1 문제를 해결하기 위해 리팩토링할 cost가 매우 클 수 있다.
위와 같은 생각으로 컬렉션을 연관 관계로 가질 때는 항상 Lazy를 사용하는 것이 좋아보인다.
이번에는 Team과 Member가 1:1의 연관 관계를 가진다
Lazy일 때, 팀을 조회하고 게터로 멤버를 꺼내는 상황을 테스트 해본다.

당연히 위와 같이 Select 문이 실행된다.
Eager일 때, 팀을 조회하고 게터로 멤버를 꺼내는 상황을 테스트 해본다.

Outer Join으로 가져온다.
예제1과 비슷해보이지만 주의해야할 점이 한 가지가 줄었다.
메모리 로드 문제를 걱정하지 않아도 된다.
아래의 조건 중 하나를 충족한다면 Eager를 사용하는 것이 좋아보인다.
Lazy로 설정하고 필요할 때만 Join해서 가져오는 것이 좋다고 생각한다.위와 같은 생각으로 단일 객체를 연관 관계로 가질 때는 상황마다 다를 것 같다.