[Refactor]#65 getMyLikedCommunities N+1 쿼리 제거 #66
Conversation
📝 WalkthroughWalkthroughModified Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (3)
src/test/java/tave/crezipsa/crezipsa/application/community/usecase/LikeUseCaseImplTest.java (2)
19-20: Move newjava.utilimports into the main Java import block.These new Java imports are currently below
org.*imports, which breaks the project’s import grouping convention.As per coding guidelines: Import grouping follows typical order: `java` → `jakarta`/`javax` → `org` → `lombok` → project packages.♻️ Proposed change
import java.util.List; import java.util.Optional; +import java.util.Collections; +import java.util.Map; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.Collections; -import java.util.Map;🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/java/tave/crezipsa/crezipsa/application/community/usecase/LikeUseCaseImplTest.java` around lines 19 - 20, The new imports java.util.Collections and java.util.Map are placed below org.* imports in LikeUseCaseImplTest.java; move these two import lines up into the primary Java import block above the org.* imports so the file follows the project import grouping order (java → jakarta/javax → org → lombok → project). Locate the import statements for Collections and Map and reposition them with other java.* imports at the top of the import section.
263-282: Add an explicitcommentCountassertion in the popular-sort test.This test verifies repository interaction, but asserting the mapped
commentCountvalue too would better match the test intent and catch mapping regressions.♻️ Proposed assertion addition
// Then assertThat(result.getContent()).hasSize(1); + assertThat(result.getContent().get(0).commentCount()).isZero(); verify(likeRepository).findMyLikedCommunitiesPopular(eq(10L), eq(CommunityField.TIP), any()); verify(commentRepository).countByCommunityIds(List.of(1L)); verify(commentRepository, never()).countByCommunityId(anyLong());🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/test/java/tave/crezipsa/crezipsa/application/community/usecase/LikeUseCaseImplTest.java` around lines 263 - 282, The test popularSort_usesBatchCommentCount currently verifies repository calls but omits asserting the mapped comment count on the response; update the test method popularSort_usesBatchCommentCount to also assert that the returned MyLikedCommunityResponse (from sut.getMyLikedCommunities(...)) has the expected commentCount (e.g., 0L as provided by commentRepository.countByCommunityIds(Map.of(1L,0L))). Locate the Slice<MyLikedCommunityResponse> result, get its single element (result.getContent().get(0)) and add an assertion against its commentCount getter to ensure mapping from commentRepository.countByCommunityIds is validated.src/main/java/tave/crezipsa/crezipsa/application/community/usecase/LikeUseCaseImpl.java (1)
89-92: Consider short-circuiting empty ID lists before repository call.When
pageis empty, skippingcountByCommunityIdsavoids an unnecessary call and removes potential empty-INquery edge cases.♻️ Proposed change
+import java.util.Collections; import java.util.List; import java.util.Map; @@ List<Long> communityIds = page.getContent().stream() .map(Community::getCommunityId).toList(); - Map<Long, Long> commentCounts = commentRepository.countByCommunityIds(communityIds); + Map<Long, Long> commentCounts = communityIds.isEmpty() + ? Collections.emptyMap() + : commentRepository.countByCommunityIds(communityIds);🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/main/java/tave/crezipsa/crezipsa/application/community/usecase/LikeUseCaseImpl.java` around lines 89 - 92, If page.getContent() is empty, avoid calling commentRepository.countByCommunityIds on an empty list: check page.getContent().isEmpty() (or communityIds.isEmpty()) after building communityIds and return an empty commentCounts map (e.g., Collections.emptyMap()) or skip the repository call; update the flow in LikeUseCaseImpl around the page -> communityIds -> commentCounts sequence so countByCommunityIds is only invoked when communityIds is non-empty.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@src/main/java/tave/crezipsa/crezipsa/application/community/usecase/LikeUseCaseImpl.java`:
- Around line 89-92: If page.getContent() is empty, avoid calling
commentRepository.countByCommunityIds on an empty list: check
page.getContent().isEmpty() (or communityIds.isEmpty()) after building
communityIds and return an empty commentCounts map (e.g.,
Collections.emptyMap()) or skip the repository call; update the flow in
LikeUseCaseImpl around the page -> communityIds -> commentCounts sequence so
countByCommunityIds is only invoked when communityIds is non-empty.
In
`@src/test/java/tave/crezipsa/crezipsa/application/community/usecase/LikeUseCaseImplTest.java`:
- Around line 19-20: The new imports java.util.Collections and java.util.Map are
placed below org.* imports in LikeUseCaseImplTest.java; move these two import
lines up into the primary Java import block above the org.* imports so the file
follows the project import grouping order (java → jakarta/javax → org → lombok →
project). Locate the import statements for Collections and Map and reposition
them with other java.* imports at the top of the import section.
- Around line 263-282: The test popularSort_usesBatchCommentCount currently
verifies repository calls but omits asserting the mapped comment count on the
response; update the test method popularSort_usesBatchCommentCount to also
assert that the returned MyLikedCommunityResponse (from
sut.getMyLikedCommunities(...)) has the expected commentCount (e.g., 0L as
provided by commentRepository.countByCommunityIds(Map.of(1L,0L))). Locate the
Slice<MyLikedCommunityResponse> result, get its single element
(result.getContent().get(0)) and add an assertion against its commentCount
getter to ensure mapping from commentRepository.countByCommunityIds is
validated.
ℹ️ Review info
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/main/java/tave/crezipsa/crezipsa/application/community/usecase/LikeUseCaseImpl.javasrc/test/java/tave/crezipsa/crezipsa/application/community/usecase/LikeUseCaseImplTest.java
문제
LikeUseCaseImpl.getMyLikedCommunities에서 페이지 내 커뮤니티 수만큼 DB 쿼리가 추가로 발생하는 N+1 문제가 있었습니다.page.map()람다 내부에서commentRepository.countByCommunityId()를 단건으로 반복 호출하기 때문에, 한 페이지에 20개의 게시글이 있으면 댓글 수 조회 쿼리만 20번 추가 실행됩니다.해결
이미
CommunityUseCaseImpl.getMyCommunities에서 동일한 문제를 배치 쿼리로 해결한 패턴이 존재합니다.getMyLikedCommunities에도 동일한 방식을 적용하여 N번 쿼리를 1번으로 줄였습니다.테스트
LikeUseCaseImplTest.getMyLikedCommunities테스트를 배치 방식에 맞게 교체했습니다.latestSort_usesBatchCommentCountcountByCommunityIds) 호출 확인, 단건 메서드(countByCommunityId) 미호출(never()) 확인, commentCount 정상 매핑 확인popularSort_usesBatchCommentCountemptyPage_callsBatchWithEmptyListmissingCommentCountEntry_defaultsToZero변경 파일
application/community/usecase/LikeUseCaseImpl.javatest/.../usecase/LikeUseCaseImplTest.javaSummary by CodeRabbit
Performance Improvements
Tests