[개념] Lazy(지연로딩)와 Eager(즉시로딩)

 

 

Lazy, Eager 한 줄 요약


  • 지연로딩, Lazy
    • 필요한 시점에 연관된 데이터를 불러오기
  • 즉시로딩, eager
    • 연관된 데이터를 한 번에 불러오기

 

JAVA Persistence API


  • 대부분 join을 이용해 SQL 한 번으로 조회한다
  • JPA에서 테이블 간 연간 관계는 객체의 참조를 통해 이루어진다
  • 서비스가 커진다 > 참조하는 객체가 많아진다 > 객체가 가지는 데이터 양이 많아진다
    • DB로부터 참조하는 객체들의 데이터를 한꺼번에 가져오는 것은 비효율적이다
    • 해결방안으로 참조하는 객체들의 데이터를 가져오는 시점을 정해버리자

Fetch Type

  • JPA의 참조하는 개체들의 데이터를 가져오는 시점을 정하기
  • 이 Fetch Type으론 Lazy방식과 Eager방식과 존재

Lazy, 지연로딩


로딩되는 시점에 Lazy로딩이 설정되어 있다면, 다음과 같은 로직을 이룬다

@ManyToOne(fetch = FetchType.LAZY)
  • A엔티티는 프록시 객체로 가져와진다
  • 실제로 A객체를 사용하는 시점에 초기화가 되면서 DB에 쿼리가 전송된다
    • 즉, getA()를 통해 프록시 객체가 조회될 것이다
    • 즉, getA().getX()를 통해, A의 필드(X)가 접근되면서 쿼리가 전송된다

A엔티티와 또 다른 a엔티티가 연관(ManyToOne)되어있고, 이를 같이 사용한다고 쳐보자

  • LAZY로딩 사용시, SELECT쿼리가 2번 발동된다
    • 이는, 네트워크가 2번에 나뉘어 조회를 이루는 비효율적인 결과를 갖는다
    • 해결책: EAGER

 

Eager, 즉시 로딩


@ManyToOne(fetch = FetchType.EAGER)

로딩되는 시점에 Eager로딩이 설정되어 있다면, 다음과 같은 로직을 이룬다

 

  • A엔티티는 프록시 객체로 가져와지지 않는다
  •  SQL 한번에 함께 조회하게 된다
    • 실제로 A객체를 사용하는 시점에서 DB상으로 쿼리가 나가는 것이 아니다

 

 

결론


  • 실무에서는 LAZY(즉시로딩) 로딩 전략이 적합하다
    • 예상치 못한 SQL 발생 가능성이 존재하기 때문이다 ( 추후 포스팅 예정)
    • 자주, 가끔 이 둘의 차이로 즉시와 지연을 구분하기도 하지만, 보편적으로 LAZY권장.
  •  LAZY(지연로딩)를 명시하여 사용해야 한다
    •  @ManyToOne, @OneToOne 등, toOne으로 끝나는 어노테이션들은 디폴트로 Eager로딩이 적용되므로 직접 설정해야 함