티스토리 뷰
즉시로딩과 지연로딩에 대해 정리해 보았다.
즉시로딩과 지연로딩을 어떤 상황에서 사용하는지,
왜 사용하는지에 대한 정리 글이다.
먼저 즉시로딩과 지연로딩을 알기 위해선 JPA의 프록시에 대한 개념을 알아야 한다.
여기서는 즉시로딩과 지연로딩에 대한 글이므로 프록시는 아래 글을 통해 간단하게 알아보고
즉시로딩과 지연로딩을 이해하도록 하자.
목차
1.프록시란
2.지연로딩
3.즉시로딩
1. 프록시란?
프록시 정의
대리, 가짜라는 의미를 가지고 있는 proxy.
프록시 사용이유
ex) Member 엔티티를 조회할 때 Team도 함께 조회해야 할까?
- 비즈니스 로직에서 필요하지 않을 때를 구분해야 한다.
- ⭐️ 낭비가 발생하게 된다.
- JPA는 이 낭비를 하지 않기 위해, 지연로딩과 프록시라는 개념으로 해결한다.
프록시 기초
- JPA에서 em.find() 말고, em.getReference()라는 메서드도 제공된다.
- em.find() 는 DB를 통해서 실제 엔티티 객체를 조회하는 메서드이고
- em.getReference()는가짜(프록시) 엔티티 객체를 조회하는 메서드이다.
2. 지연로딩
지연로딩은 아래와 같이 @OOOToOne으로 끝나는 어노테이션에 fetch = FetchType.LAZY를 선언해준다.
@ManyToOne(fetch = FetchType.LAZY)
⭐️ 지연로딩 적용 시 DB가 아닌 프록시에서 가져온다!
프록시는 가짜 객체라고 했다. 낭비를 줄이기 위해 실제 DB가 아닌
엔티티 모양을 한 프록시라는 가짜 객체에서 엔티티 정보를 가져온다.
Member와 Team 클래스 예제
지연로딩 미적용 시
@Entity(name = "Member")
@Getter
public class Member extends BaseTimeEntity{
@ManyToOne
@JoinColumn(name = "team_id")
private Team team;
}
지연로딩 적용 시
@Entity(name = "Member")
@Getter
public class Member extends BaseTimeEntity{
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Team team;
}
결론
지연로딩을 사용하게 되면 Member와 Team이 각각 분리되어
Member는 DB를 조회하고, Team은 프록시를 조회한다고 이해했다.
쿼리 또한 Member 조회 쿼리 한 번, Team 조회 쿼리 한 번 분리되어 나간다.
즉 성능이 더 뛰어나다.
이를 통해서 Member를 조회할 때 Team을 조회할 필요가 없다면
지연로딩을 걸어서 분리하도록 하자.
반대로 만약 내 서비스는 Member를 조회할 때 Team의 정보도 같이 알고 싶다면
즉시로딩을 적용하면 된다.
3. 즉시로딩
@ManyToOne(fetch = FetchType.EAGER)
⭐️ 즉시로딩은 실제 DB에서 한 방에 조회
소제목의 글을 보면 즉시로딩의 핵심이 다 담겨 있다.
즉시로딩을 적용한다면 Member와 Team을 실제 DB에서 한 번에 조회해서
하나의 쿼리로 가져온다.
⭐️ 실무 꿀팁(프록시와 즉시로딩 주의 )
김영한님 말씀 참고하여 작성했습니다.
- 가급적 지연로딩만 사용
- 즉시로딩을 사용하면 예상치 못한 SQL 문제 발생
- 즉시로딩은 JPQL에서 n+1 문제를 발생
- @ManyToOne / @OneToOne은 기본이 즉시로딩 -> LAZY로 변경해야 함
- @ManyToMany / @ OneToMany는 기본이 지연로딩
문제 발생이유(SQL오류가 나는 이유)
내가 예상한 쿼리가 아닌 다른 쿼리가 나갈 수 있다.
왜?
fetch = FetchType.EAGER로 묶여있을 경우
Member만 조회를 필요로 했으나, Team 정보도 같이 나오기 때문!!
이문제가 n + 1로 발생할 수 있고, 서비스가 커지면 걷잡을 수 없다.
결론
즉시로딩의 문제들로 인해
실제론 즉시로딩을 사용하지 않는다.
부족한 내용이 있다면 댓글 부탁드립니다 감사합니다.
'💻 개발 > JPA, Querydsl' 카테고리의 다른 글
[JPA] Lazy 로딩 Jackson Serialize 에러, @JsonIgnore말고 더 나은 방법 제시 (0) | 2023.02.16 |
---|---|
[Querydsl] Querydsl과 DTO와 BooleanBuilder를 활용하여 조회하기 (0) | 2023.01.25 |
[JPA] JPA의 OSIV란? OSIV 적용예제, OSIV 성능최적화 방법 (0) | 2022.08.29 |
[Querydsl] 연관관계가 없는 테이블 연결 하기 / 연관관계 없는 엔티티 외부조인 (0) | 2022.08.16 |
[JPA] @Inhertance 조인 전략 / 상속관계 매핑 (0) | 2022.07.30 |
- Total
- Today
- Yesterday