채팅방 목록 조회 기능 성능 개선 #346
kwonyj1022
started this conversation in
참고자료
Replies: 1 comment 1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
상황
1. 도메인 구조
2. 채팅방 목록 조회 정책
(B 채팅방이 최근에 생성되었더라도 B 채팅방보다 과거에 만든 A 채팅방에서 가장 최근에 대화를 나눴다면 A 채팅방이 우선순위가 더 높음)
처음 구현했을 때
도메인 구조 상 채팅방이 메시지를 갖고 있지 않기 때문에 채팅방을 조회할 때 어떻게 해야할 지 막막했다.
위의 과정을 하나의 쿼리로 하기 어렵다고 판단했다.
따라서 차선책으로
이런 복잡한 과정을 거쳤다.
(아래 코드는 코드를 단순하게 하기 위해 fetch join 과정을 생락했다.)
첫 번째 개선
ChatRoomRepository
에서 채팅방 목록을 조회해 올 때 마지막 메시지가 최근인 순으로List<ChatRoom>
을 가져오도록 개선하였다.두 번째 개선
지금까지는 QueryDsl을 사용할 때 Projection 대상은 1개였다.
프로젝션 대상을 2개 이상 지정할 수 있다고 한다.
크게는 Tuple을 사용하는 방법과 별도의 Dto를 사용하는 방법이 있다.
1. Tuple을 사용하는 방법
별도의 Dto를 사용하는 방법
총 4가지의 방법이 있는데, ChatRoom 뿐만 아니라, QMessage까지 접근해서 Message도 가져와야 했기 때문에 조회 쿼리가 잘못되었는지 확인하기 위해 임시로 제일 위에 있던 방법인 프로퍼티 접근 방식을 사용해서 테스트하려고 했다.
이 과정에서 예상치 못한 문제가 발생해서 관련 내용을 함께 설명해보려고 한다.
팀 컨벤션 상 dto는 record를 사용하기로 했기 때문에 처음에는 record로 만들었다.
1. 프로퍼티 접근
Projections.bean(해당Dto.class, 적용할 필드...)
사용이렇게 했더니
ExpressionException
이 발생했다.처음에는 쿼리에 문제가 있는 줄 알고 쿼리를 이것 저것 바꿔보다가 시간이 많이 지체됐다.
결과적으로 문제의 원인은 record를 사용했다는 것에 있었다.
record로 작성했던 dto를 class로 바꾸고, 기본 생성자와 getter(), setter()를 모두 추가해준 후 어느 메서드가 실행되는지 알기 위해 각 메서드 실행 시 콘솔에 출력하도록 했다.
출력된 내용
출력된 내용을 보면 알 수 있듯이
프로퍼티 접근 방식은 기본 빈 생성자와 setter를 통해 dto를 생성한다.
record에는 빈 생성자도, setter도 없기 때문에 dto에 값을 할당해줄 수 없어서 예외가 발생한 것이다.
2. 필드 직접 접근
Projections.fields(해당Dto.class, 적용할 필드...)
사용이 방식도 마찬가지로
ExpressionException
이 발생했다.이것도 record를 사용했기 때문에 발생한 문제였다.
똑같이 record를 class로 바꾸고 생성자와 getter, setter 메서드를 만들고, 각 메서드마다 콘솔에 출력하도록 한 후 테스트를 실행해 보았다.
출력된 내용
출력된 내용을 보면 알 수 있듯이
필드 직접 접근 방식은 기본 빈 생성자만 사용한다.
setter를 제거하고 실행해도 정상적으로 동작한다.
하지만 record에는 빈 생성자가 없기 때문에 예외가 발생한다.
3. 생성자 사용
Projections.constructor(해당Dto.class, 적용할 필드...)
사용출력된 내용
출력된 내용을 보면 알 수 있듯이
생성자 사용 방식은 매개변수가 있는 생성자만을 사용한다.
따라서 record를 사용해도 예외가 발생하지 않는다.
4.
@QueryProjection
사용사용할 dto의 생성자에
@QueryProjection
어노테이션을 붙여준다.new QDto()
형식으로 사용할 수 있다.Beta Was this translation helpful? Give feedback.
All reactions