위와 같은 Member, Team 엔티티로 즉시로딩과 지연로딩을 알아보겠습니다.
지연로딩(LAZY)
단순히 그림으로만 알아본다면 Member 엔티티에서 Team 엔티티는 프록시로 걸리게되어 실제 Team 엔티티를 사용하는 시점에 DB를 조회하게 됩니다. 코드로 살펴보자면
Member 엔티티의 Team 연관관계에 LAZY를 걸어주고
위의 코드를 통해 결과를 확인하려 합니다. 결과를 먼저 예상해보자면 다음과 같습니다.
- Team 엔티티는 프록시 일것이고,
- 쿼리문에 Team을 조회하는 쿼리문은 나오지 않을것이고
- ======안에 실제 Team을 사용하는 메소드가 있으므로 그 안에 Team을 조회하는 쿼리문이 나올것이다.
결과를 살펴보면,
- Team은 프록시 엔티티로,
- Member만 조회하는 쿼리문이 나오고,
- Team 의 getName() 을 메소드를 호출하였을때, 실제 Team을 조회하는 쿼리가 실행되는 것을 확인 할 수 있다.
예상과 같은 결과로 나오게 되는 것을 알 수 있습니다.
즉시로딩(EAGER)
그렇다면 만약 서비스에서 Member를 조회할 때, Team까지 같이 조회해야하는 경우가 대부분이라면 어떡할까요?
그럴때 즉시로딩을 통해서 결과를 한번에 구해올 수 있습니다.
연관관계에 EAGER를 걸어주고
같은 실행코드를 통해 결과를 확인해 보면,
- 최초 쿼리문에 Member와 Team을 한번에 조회하게 되고
- 프록시 객체가 아닌 실제 엔티티가 호출되며
- 이미 위에서 Member와 Team의 정보를 다 받아왔으므로 별도의 쿼리문 없이 바로 TeamName의 값을 받아온다.
라는 결과를 확인할 수 있습니다.
그래서 무엇을...?
위의 예시를 통해서 즉시로딩과 지연로딩에 대해서 확인을 해봤습니다. 그럼 상황에 맞게 각각 방식을 잘 활용하면 되는걸까요?
-> 그건 X 라고 합니다. 실무에서는 모든 연관관계에 지연로딩을 사용하라고 많은 자료에 나와 있습니다.
그 이유는 무엇일까요? 다음과 같은 이유들이 있습니다.
- 즉시 로딩을 적용하면 예상치 못한 SQL이 발생 → 위의 예시에선 연관관계가 2개뿐이어서 즉시로딩을 했을때 비교적 간단한 쿼리문이 나왔지만, 실무에선 다르다.
- 즉시 로딩은 JPQL에서 N + 1 문제를 일으킨다. → 1개의 최초 쿼리를 제외한 N개의 쿼리문이 추가로 발생한다.(성능 문제로 이어진다.)
위와 같은 이유로 지연로딩을 사용을 권장하고 있습니다.
'Spring Data' 카테고리의 다른 글
페치 조인(fetch join)이란? (0) | 2021.12.03 |
---|---|
프록시란? (0) | 2021.11.26 |
엔티티의 생명주기 (0) | 2021.11.24 |
영속성 컨텍스트 (0) | 2021.11.24 |