Step 1: 방 및 권한 검증
bookCommandPort.findBookByRoomId(roomId): 도서 정보 조회.roomParticipantCommandPort.findByUserIdAndRoomIdOptional(userId, roomId): 사용자의 방 참여 여부 및 권한 검증.Step 2: 조회 타입(Type)에 따른 로직 분기
GROUP(그룹 전체)과MINE(내 기록)에 따라 필터 검증 및 정렬 로직 수행.
isOverview 여부에 따라 페이지 시작/끝 값을 설정하고 정렬 조건(LATEST, LIKE, COMMENT)에 따라 데이터를 조회.Step 3: 보조 데이터 일괄 조회 (In-memory Join)
VOTE) 타입의 postId를 추출하여 관련 항목을 일괄 조회.[테스트 환경]
[1차 부하 테스트 결과]
| 조회 시나리오 | 평균 응답 시간 | 최대 응답 시간 | 비고 |
|---|---|---|---|
| 최신순 (그룹) | 약 6.7s | 7.1s | 정렬 조건 존재 |
| 댓글순 (그룹) | 약 9.7s | 10.2s | 인덱스 미설정 |
| 좋아요순 (그룹) | 약 9.4s | 10.6s | 인덱스 미설정 |
| 내 기록 조회 | 약 3.0s | 4.0s | - |
댓글순이나 좋아요순은 인덱스가 없어 느린 것이 당연했지만, PK를 사용하는 최신순 정렬이 7초나 걸리는 점은 의문이었습니다. 원인은 Querydsl의 정렬 로직에 있었습니다.
[기존 코드의 문제점]
case CREATED_AT -> {
LocalDateTime createdAt = cursor.getLocalDateTime(0);
Long postId = cursor.getLong(1);
builder.and(post.createdAt.lt(createdAt)
.or(post.createdAt.eq(createdAt).and(post.postId.lt(postId))));
}
createdAt과 postId를 복합 정렬 조건으로 사용하고 있었습니다. 하지만 우리 시스템은 AUTO_INCREMENT 전략을 사용하므로, postId가 클수록 최신 데이터임이 보장됩니다. 즉, createdAt 정렬은 불필요한 비용을 발생시키고 있었습니다.
[개선 코드]
case CREATED_AT -> {
Long postId = cursor.getLong(0);
builder.and(post.postId.lt(postId));
}