Back-end/Spring

[SpringBoot] 지연 로딩과 즉시 로딩

poppy 2022. 3. 31. 14:38
반응형

지연 로딩

Member와 Team이 연관 관계를 맺고 있다고 할 때, Member를 조회하면 Team도 함께 조회된다.

단순히 Member 정보만 필요할 경우 Member를 조회할 때 Team도 함께 조회해야 할까?

이것을 해결할 수 있는 것이 '지연 로딩'이고, 지연 로딩 LAZY를 사용해서 프록시로 조회하는 방법으로 해결한다. 다음과 같이 지연 로딩을 적용할 수 있다.

 

로딩되는 시점에 Lazy 로딩 설정이 되어있는 Team 엔티티는 프록시 객체로 가져온다.

나중에 실제 team 객체를 사용하는 시점에 초기화가 되고, DB에 쿼리가 나간다.

  • getTeam()으로 Team을 조회하면 프록시 객체가 조회가 된다.
  • getTeam().getXXX()으로 Team의 필드에 접근 할 때, 쿼리가 나간다.
@Entity
public class Member {
    @Id
    @GeneratedValue
    private Long id;
    
    @Column(name = "USERNAME")
    private String name;
    
    @ManyToOne(fetch = FetchType.LAZY) // 지연 로딩
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    .. 
 }

 

즉시 로딩

하지만, Member와 Team을 자주 함께 사용한다면? 지연 로딩을 사용하면 쿼리가 2번 나가기 때문에 비효율적이다.

이것을 해결할 수 있는 것이 '즉시 로딩'이고, 즉시 로딩 EAGER을 사용해서 한 번에 조회할 수 있다. 다음과 같이 즉시 로딩을 적용할 수 있다.

 

로딩되는 시점에 EAGER 로딩 설정이 되어있는 Team 엔티티는 실제 객체로 가져온다.

  • getTeam()으로 Team을 조회하면 실제 객체가 조회가 된다.
@Entity
public class Member {
    @Id
    @GeneratedValue
    private Long id;
    
    @Column(name = "USERNAME")
    private String name;
    
    @ManyToOne(fetch = FetchType.EAGER) // 즉시 로딩
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    .. 
 }

 

주의할 점

실무에서 가급적 지연 로딩만 사용하는 것이 좋다!

즉시 로딩을 적용하면 예상하지 못한 SQL이 발생할 수 있다. 그리고 즉시 로딩은 JPQL에서 N+1 문제를 일으킨다.

  • @ManyToOne, @OneToOne은 기본이 즉시 로딩이므로 LAZY로 설정이 필요하다.
  • @OneToMany, @ManyToMany는 기본이 지연 로딩이다.
반응형