이전에 살펴본 제로 오프셋 페이징을 이용한 페이징 성능 개선과 N+1 문제 해결을 네이티브 쿼리로 진행해보았다.

엔티티간의 어노테이션을 통한 연관관계를 지우고
외래키를 지정해주었다.

쿼리는 다음과 같이 작성했다.

테이블의 모든 정보를 가져오는게 아닐 때에는 이렇게 인터페이스로 가져와야 한다고 한다.
(키워드: 프로젝션)

Hibernate: select member0_.id as id1_5_, member0_.email as email2_5_, member0_.nickname as nickname3_5_, member0_.point as point4_5_, member0_.thumbnail as thumbnai5_5_ from member member0_ where member0_.email=?
Hibernate: SELECT Article.id as id, Article.title as title, Article.body as body ,Article.member_id as memberId, Member.nickname as nickname FROM Article INNER JOIN Member ON Article.member_id=Member.id where Article.id> ? limit ?

결과는 이렇게 속도도 개선되고, 쿼리도 원하는 만큼만(인증, 조회 쿼리) 두개만 나가는 것을 알 수 있다.

하지만 이게 최선의 해결 방법이라는 생각이 들진 않았다.

네이티브 쿼리를 이용하고, 연관관계 해소를 선택한 이유는 다음과 같다.

  1. 네이티브 쿼리를 사용하면 jpql의 한계를 고려할 필요 없이 바로 사용가능하다.
  2. 성능 만을 고려했을 때에는 네이티브 쿼리가 가장 빠르다.
  3. 네이티브 쿼리와 친해지고 싶었다.
  4. Jpa 연관관계를 언제나 사용할 수 있는것은 아니고, 연관관계가 야기하는 문제점들도 분명히 존재한다.

이러한 이유에도 불구하고, 현재 연관관계를 해소했던 것을 다시 되돌려서 네이티브 쿼리가 아닌 QueryDsl로 작성하고자 한다. 이러한 결정을 내린 이유는 다음과 같다.

  1. .getXX와 같은 객체지향적인 코드를 작성할 수 없다.

연관관계를 사용하지 않는다면 Article-Member의 관계가 다대일인 상황에서 articleA.getMember() 같은 메소드를 이용할 수 없다. 물론 그걸 감안하고 진행했었지만 생각보다 생산성에 큰 영향을 준다는 생각이 들었다.

연관관계를 해소하니 수정해야했던 코드가 꽤나 많았음을 생각하니, 규모가 더 컸더라면 수정했어야 했던 코드도 훨씬 많았으리라 생각된다.

*근데 서비스 레이어에서 다른 도메인의 레포지토리를 의존하는게 아니라 각각의 서비스레이어를 의존하다보니, 연관관계를 해소함에 있어서 그 도메인 코드들만 코드를 수정해주면 되었다. 의존성 방향에 대해 고민했던 보람이 있었다..
https://velog.io/@chs98412/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EB%A6%AC%ED%8C%A9%ED%86%A0%EB%A7%81-1

  1. 네이티브 쿼리의 가독성

네이티브 쿼리가 Jpa 네이밍 메소드보다는 가독성이 좋지만, 조금만 길어져도 가독성이 떨어지는 문제가 있었다. 따라서 QueryDsl을 이용할 예정이다.

  1. 페치 조인

N+1 문제를 해결하기 위해 네이티브 쿼리로 inner 조인을 사용했다. 이는 jpql에서 페치 조인을 사용했을 때 실 쿼리는 inner 조인이 나가서 네이티브 쿼리도 그렇게 작성했던건데, 찾아보니 페치 조인은 inner 조인과는 조금 다르다고 한다.

페치조인은 join으로 묶여온 정보들도 영속성 컨텍스트에 보관하고, inner 조인은 조회하는 주체가 되는 Entity만 영속화한다고 한다. 따라서 N+1이 발생하던 그 당시에는 페치조인을 사용하던 inner 조인을 사용하던 쿼리가 하나만 나가서 문제가 해결된 것으로 보이겠지만, 후에 다른 메소드를 실행할 때, 페치조인은 영속성 컨텍스트에 영속화된 정보를 불러와서 쿼리를 아끼겠지만, inner 조인은 그렇지 못하고 쿼리를 더 날리게 된다. 이러한 문제를 생각하니, 영속성 컨텍스트를 올바르게 사용하기 위해선 jpql을 이용해서 쿼리를 작성하는게 좋을 것 같다는 생각이 들었다.

  1. 프로젝트 규모

Jpa 연관관계가 주는 다양한 문제점들이 있지만, 아직까진 프로젝트의 규모도 크지 않고, 문제점이 주는 단점보다는 장점들이 주는 장점이 큰 상황이라고 생각했다.

따라서 다시 되돌리고, QueryDsl을 사용하기로 했다.

profile
🙂 🙃 🙂 🙃

0개의 댓글