저번에 쓴 블로그글 프록시에 대해 이해하고 오면 지연로딩에 대해 이해하기 수월하다.
2023.06.28 - [Spring/이론] - JPA 기본 - 프록시 객체
프록시 객체는 그 안에 target으로 하는 엔티티 객체가 처음에 비워져 있다.
-> .getName()과 같이 실제 값에 접근할 때에 쿼리를 날리고 엔티티 객체를 채워넣는다.
처음에 member에 대한 select문만 db에 날리고,
이후에 member.getTeam().getName()과 같이 팀 내부 값을 조회할 때
team에 대한 select문을 날려 쿼리 조회 횟수를 최소화하는 것이다.
지연 로딩과 즉시 로딩에 대한 사용방식은 다음과 같다.
// 지연 로딩
@ManyToOne(fetch = fetchType.LAZY)
@JoinColumn(name = "TEAM_ID")
private Team team;
// 즉시 로딩
@ManyToOne(fetch = fetchType.EAGER)
@JoinColumn(name = "TEAM_ID")
private Team team;
즉시로딩은 member만 조회하더라도 연결되어 있는 모든 엔티티에 대해 전부 조회해오는 기능이다.
member와 team, image, roles등 여러 엔티티가 연결되어 있다면 연결되어있는 모든 엔티티에 대해 join을 걸어 한번에 select문을 날리는 것이다.
이럴 경우 불필요한 쿼리가 많이 나가게 되어 성능에 문제가 생긴다.
따라서 실무에서는 가급적 지연 로딩만 사용하는 것으로 한다.
즉시 로딩은 사용을 지양하자
- 즉시 로딩을 적용하면 예상하지 못한 SQL문이 발생한다. (과도한 JOIN문 등)
- JPQL 사용 시에 N + 1 문제를 일으킨다. N + 1 문제란 1번의 쿼리를 날렸을 때 N번의 쿼리가 추가로 나가는 문제를 말한다.
- SELECT문 사용시 LAZY + fetch join을 걸지 않으면 MEMBER를 한번 조회해온 후 모든 TEAM에 대해 한번씩 다 조회를 해온다.
- MEMBER에 대한 쿼리가 끝난 후 각 MEMBER에 대한 TEAM의 값이 비어 있어 이를 채워주기 위해 N번 더 TEAM객체를 조회해오는 SELECT문을 날리는 것이다.
- @ManyToOne, @OneToOne은 기본이 즉시 로딩이니 LAZY로 꼭 설정해주자.
'Spring > 이론' 카테고리의 다른 글
Spring Security 동작 원리 / 필터 순서 (0) | 2023.07.05 |
---|---|
JPA - 영속성 전이, 고아 객체 (0) | 2023.06.29 |
JPA 기본 - 프록시 객체 (0) | 2023.06.28 |
웹 애플리케이션 이해 (0) | 2022.07.14 |
빈 스코프(Bean Scope)란? (0) | 2022.07.04 |