조회 엔티티가 양방향 참조하고 있을 경우 계속 상대 엔티티를 json 으로 파싱하기 위해 찾아 들어가 무한 루프 발생
엔티티를 json 으로 바꾸는 중 지연 로딩에 의해 연결된 엔티티들이 프록시 객체로 들어가 있으므로 에러가 발생
조회 엔티티와 양방향 참조된 엔티티에서 @JsonIgnore 어노테이션을 참조관계 필드에 설정하여 json 파싱 무한루프에 빠지지 않도록 할 수 있음
Hibernate5Module 라이브러리를 사용하여 지연 로딩 객체를 강제로 불러와 json 으로 파싱하거나, 지연 로딩으로 설정된 엔티티들은 null 값으로 채워 반환할 수 있음
이정도면 엔티티 직접 반환하지 말라고 그만 말해도 될 것 같다.
DTO List 를 반환하는 API 가 있다고 했을 때, 엔티티마다 DTO 로 변환하는 과정에서, 참조하는 다른 엔티티의 필드값을 가져와야 한다면, N + 1 문제가 발생하게 된다.
지연 로딩 쓰지말고 EAGER 로딩으로 설정하면 되는거 아님?
-> JPQL 로 한번에 여러 열을 가져올 시 SELECT 절에 있는 컬럼만 가져오고, 이후 연관관계가 설정된 엔티티들을 가져오기 위한 쿼리를 추가로 날리게 됨. EAGER 로딩 관계가 더 있다면 쿼리가 전파되어 무수히 많은 쿼리가 발생할 수 있음.
fetch join 을 활용하여 필요한 데이터를 한 번에 불러와 N + 1 문제를 해결할 수 있다.
그러나, 지금까지의 방법으로는 fetch join 을 통해 클라이언트에게 반환할 데이터만 가져오는 것이 아니라, 연관 엔티티의 필드 전체를 가져온다는 단점이 남아있다.
JPA 에서는 JPQL 내부에서 new 를 사용하여 DTO 를 바로 생성해서 반환하는 기능을 사용할 수 있다.
원하는 컬럼만 조회하여 엔티티 전체를 조회하는 것보다 성능을 조금 더 높일 수 있다. (미세한 차이)
정확하게 해당 컬럼만 조회해오므로 재사용성이 떨어진다는 단점도 존재한다.
또, Repository 레이어에서 api 스펙을 위해 만들어진 DTO 를 사용한다는 것이 논리적으로 좋지 않다. (API 스펙이 바뀌면, Repository 단 코드를 변경해야한다.)
엔티티를 DTO로 변환하는 방법을 선택
필요 시, 페치 조인으로 성능 최적화 (대부분의 이슈가 이 단계에서 해결)
그래도 안되면 DTO로 직접 조회
최후의 방법으로 JPA가 제공하는 네이티브 SQL 이나 JDBC Template을 사용하여 직접 SQL을 사용