X to One 연관 관계의 성능 최적화를 하기위해 먼저 알아야 할 것은 즉시(Eager) 로딩과 지연(Lazy) 로딩의 차이이다.
Member.java
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@Entity
@Getter
@Setter
public class Member {
@Id
@GeneratedValue
private Long id;
private String name;
@ManyToOne(fetch = FetchType.EAGER)
private Team team;
}
|
Team.java
1
2
3
4
5
6
7
8
9
10
11
12
13
|
@Entity
@Getter
@Setter
public class Team {
@Id
@GeneratedValue
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
}
|
간단하게 두 엔티티의 연관 관계를 만들어주고, FetchType.EAGER
로 설정을 해두었다.
간단한 엔티티 테스트 코드를 통해 쿼리문을 확인해보도록 하자.
MemberTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
@SpringBootTest
@Transactional
class MemberTest {
@PersistenceContext
EntityManager em;
@Test
public void testEntity() {
Team teamA = new Team("teamA");
em.persist(teamA);
Member member1 = new Member("member1", 10, teamA);
em.persist(member1);
// 초기화
em.flush();
em.clear();
// 확인
em.find(Member.class, member1.getId());
}
}
|
결과
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
Hibernate:
select
m1_0.member_id,
m1_0.age,
t1_0.team_id,
t1_0.name,
m1_0.username
from
member m1_0
left join
team t1_0
on t1_0.team_id=m1_0.team_id
where
m1_0.member_id=?
|
FetchType.EAGER
로 설정되어 있을 때는 이와 같이 member만 조회했음에도 team까지 함께 join되어 결과 값을 가져온다.
다음은 FetchType.LAZY
로 설정했을 때의 결과 값이다.
결과
1
2
3
4
5
6
7
8
9
10
|
Hibernate:
select
m1_0.member_id,
m1_0.age,
m1_0.team_id,
m1_0.username
from
member m1_0
where
m1_0.member_id=?
|
FetchType.LAZY
로 설정되어 있을 때는 team까지는 가져오지 않고 조회한 member만 가져오게 된다.
JPA에서 X to One 연관 관계의 기본 값은 FetchType.EAGER
로 설정되어 있다. 이로 인해 필요치 않은 데이터가 같이 조회되며 N+1 문제를 일으킬 수 있다.
지연 로딩을 피하기 위해 FetchType.EAGER
로 설정하는 것은 성능 튜닝을 어렵게 만드는 지름길이다.
성능 최적화가 필요한 경우에는 Fetch Join
을 사용하면 된다. 다음 편에서는 이 fetch join을 사용하여 성능 최적화하는 방법을 알아보도록 하자.