fix: Join Fetch 중 영속성 컨텍스트 관련 문제 해결#282
Conversation
|
Caution Review failedThe pull request is closed. 📝 WalkthroughWalkthroughAdded a repository query that returns chatRoomId/userId pairs and updated ChatService to use ID-based helpers (getRoomUserIdsMap and findNonAdminUserFromIds) to resolve non-admin users and compute admin direct chat rooms without fetching full ChatRoomMember entities. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
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)
Comment |
There was a problem hiding this comment.
Pull request overview
관리자 다이렉트 채팅방 목록 조회 시 JOIN FETCH로 인해 발생하던 영속성 컨텍스트 관련 문제를 줄이기 위해, 채팅방 멤버 조회에서 User를 fetch join 하지 않도록 조회 방식을 분리한 PR입니다.
Changes:
- 관리자 다이렉트 채팅방 요약 조회에서 멤버 조회를
fetch join user없는 쿼리로 변경 ChatRoomMemberRepository에JOIN FETCH없는 조회 메서드 추가ChatService에 관리자 전용 멤버 맵 구성 헬퍼 메서드 추가
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/main/java/gg/agit/konect/domain/chat/service/ChatService.java | 관리자 다이렉트 채팅방 요약 구성 시 멤버 조회를 User 비-fetch 방식으로 변경하고, userId 기반으로 사용자 정보를 별도 로딩 |
| src/main/java/gg/agit/konect/domain/chat/repository/ChatRoomMemberRepository.java | JOIN FETCH crm.user 없이 chatRoomIds로 멤버를 조회하는 JPQL 메서드 추가 |
| private Map<Integer, List<ChatRoomMember>> getRoomMembersMapWithoutUser(List<ChatRoom> rooms) { | ||
| if (rooms.isEmpty()) { | ||
| return Map.of(); | ||
| } | ||
|
|
||
| List<Integer> roomIds = rooms.stream().map(ChatRoom::getId).toList(); | ||
| return chatRoomMemberRepository.findByChatRoomIdsWithoutUser(roomIds).stream() | ||
| .collect(Collectors.groupingBy(ChatRoomMember::getChatRoomId)); | ||
| } |
There was a problem hiding this comment.
getRoomMembersMap()와 getRoomMembersMapWithoutUser()가 로직이 거의 동일해서(빈 리스트 처리/roomIds 추출/groupingBy) 중복이 생깁니다. 공통 메서드로 추출하고 repository 호출만 주입(예: Function<List, List>)받도록 정리하면 향후 조회 방식이 늘어날 때 유지보수가 쉬워집니다.
| FROM ChatRoomMember crm | ||
| WHERE crm.id.chatRoomId IN :chatRoomIds | ||
| """) | ||
| List<ChatRoomMember> findByChatRoomIdsWithoutUser(@Param("chatRoomIds") List<Integer> chatRoomIds); |
There was a problem hiding this comment.
findByChatRoomIdsWithoutUser는 실제로는 “user를 제외”하는 게 아니라 JOIN FETCH crm.user를 하지 않는 조회라서, 이름만 보면 의미가 모호할 수 있습니다. 기존 findByChatRoomIds가 fetch join을 포함하고 있으니, 메서드명을 ...FetchUser/...WithoutFetch처럼 의도를 더 직접적으로 드러내거나(또는 기본 메서드를 non-fetch로 두고 fetch 메서드를 별도 명명) 혼동을 줄이는 편이 안전합니다.
| List<ChatRoomMember> findByChatRoomIdsWithoutUser(@Param("chatRoomIds") List<Integer> chatRoomIds); | |
| List<ChatRoomMember> findByChatRoomIdsWithoutFetch(@Param("chatRoomIds") List<Integer> chatRoomIds); |
| @Query(""" | ||
| SELECT crm | ||
| FROM ChatRoomMember crm | ||
| WHERE crm.id.chatRoomId IN :chatRoomIds | ||
| """) | ||
| List<ChatRoomMember> findByChatRoomIdsWithoutUser(@Param("chatRoomIds") List<Integer> chatRoomIds); |
There was a problem hiding this comment.
현재 사용처(관리자 다이렉트 룸 요약)에서는 chatRoomId/userId만 필요합니다. 그런데 findByChatRoomIdsWithoutUser가 ChatRoomMember 엔티티를 그대로 반환하면 결과가 영속성 컨텍스트에 적재/더티체킹 대상이 될 수 있으니, 가능하면 (chatRoomId, userId)만 담는 프로젝션/DTO 조회로 바꾸면 메모리·영속성 컨텍스트 부담을 더 줄일 수 있습니다.
🔍 개요
🚀 주요 변경 내용
💬 참고 사항
✅ Checklist (완료 조건)
Summary by CodeRabbit