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로딩이 적용되므로 직접 설정해야 함