이론 정리/Spring boot

FetchType Eager vs Lazy

철매존 2022. 6. 17. 22:00
728x90

JPA에서는 여러 엔티티가 서로 연관되어 있을 때에, 하나의 엔티티에서 다른 엔티티를 두가지 방법으로 찾는데, 간단히 말하면 해당 엔티티를 검색할때 바로 찾거나(Eager) 혹은 해당 엔티티를 사용할 때 찾거나(Lazy) 로 나뉜다.

이 내용들에 관해서 알아보도록 한다.

LAZY전략

  • FetchType.LAZY

지연 전략이라고도 한다.
fetchType을 LAZY로 설정하면, 이 지연로딩의 대상이 된 쪽은 프록시 객체로 가져오게 된다.
그리고 이후에 해당 대상을 실제로 사용하려 할 때에 초기화가 진행된다.

XToMany의 기본 속성이 LAZY로 되어 있다.

Eager전략

  • FetchType.EAGER

즉시 전략이라고도 한다.
fetchType을 EAGER로 설정하면, 로딩할 때에 모든 값을 join하여 가져온다. 그렇기 때문에 이렇게 가져오면 프록시로 가져오지 않고 실제 엔티티를 가져온다.

XToOne의 기본 속성이 EAGER로 되어 있다.

Eager전략은 가급적 쓰지 말자!!

실무에서 Eager전략의 사용은 지양되고, 되도록이면 LAZY전략을 쓰도록 하고 있다.
이 이유는 다음과 같은데

  1. 즉시 로딩을 사용할 경우 전혀 예상하지 못한 SQL이 나타날 확률이 높다.

-> 정말 간단히 말해서, 즉시 다른 객체를 가져올 때에 join을 사용해서 가져올지, select를 두 번 날릴지 아무도 모른다.

  1. join이 여러번 걸리게 되는 경우 성능상 문제가 발생할 수 있다.

-> 당장 쓸 이유가 없는 친구인데 이걸 join을 써서 일단 가져오게 된다면, 성능상에 문제가 발생할 수 있다.(join의 시간복잡도는 지수함수로 증가하기 때문) 그렇기 때문에 사용할 필요가 없는 경우를 대비하는것이 좋을 것이다.

  1. 즉시로딩은 JPQL에서 N+1문제의 원인이 된다.

-> JPQL은 JPA와 달리 최적화가 되어있는 것이 아니라 SQL로 변환만 해주는 친구이기 때문이다.
-> 위의 1번에서 select를 여러 번 날리는 쿼리가 이 때에 많이 발생하게 된다.

이런 문제들로 인해 실무에서는 EAGER를 사용하지 않는다.
LAZY로 하면 어쨌든 이런 문제들은 해결할 수 있기 때문

결론

그러니까 XToOne, XToMany 이런 것들과 상관없이 모두 LAZY로 설정해주면 된다.
물론 LAZY로 하는 경우도 많은 데이터가 연관되어 있는 경우 당연히 N+1문제가 발생할 수 있다.(사실 LAZY가 더 N+1의 발생 문제에서는 자유롭지 못하다)
이는 fetch join / Entity Graph 등으로 해결하면 될 것이다.