Skip to content

fix: Join Fetch 중 영속성 컨텍스트 관련 문제 해결#282

Merged
JanooGwan merged 2 commits intodevelopfrom
fix/chat-room-opponent-name
Feb 20, 2026
Merged

fix: Join Fetch 중 영속성 컨텍스트 관련 문제 해결#282
JanooGwan merged 2 commits intodevelopfrom
fix/chat-room-opponent-name

Conversation

@JanooGwan
Copy link
Contributor

@JanooGwan JanooGwan commented Feb 20, 2026

🔍 개요

  • close #이슈번호

🚀 주요 변경 내용

  • Join Fetch 중 영속성 컨텍스트 관련 문제가 존재했어서 이를 해결했습니다.

💬 참고 사항


✅ Checklist (완료 조건)

  • 코드 스타일 가이드 준수
  • 테스트 코드 포함됨
  • Reviewers / Assignees / Labels 지정 완료
  • 보안 및 민감 정보 검증 (API 키, 환경 변수, 개인정보 등)

Summary by CodeRabbit

  • Refactor
    • Improved admin direct chat room processing to fetch and work with member IDs instead of full member records, excluding the admin earlier to reduce data loading and simplify user-resolution logic, while preserving existing unread counts and room summaries.

@JanooGwan JanooGwan requested a review from Copilot February 20, 2026 04:55
@JanooGwan JanooGwan self-assigned this Feb 20, 2026
@JanooGwan JanooGwan added the 버그 정상적으로 동작하지 않는 문제 상황 관련 이슈입니다. label Feb 20, 2026
@coderabbitai
Copy link

coderabbitai bot commented Feb 20, 2026

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

Added 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

Cohort / File(s) Summary
Repository: ID-pair query
src/main/java/gg/agit/konect/domain/chat/repository/ChatRoomMemberRepository.java
Added findRoomMemberIdsByChatRoomIds(@param("chatRoomIds") List<Integer>) returning List<Object[]> of (chatRoomId, userId) pairs (no JOIN FETCH).
Service: ID-based helpers & admin flow
src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
Replaced member-entity processing in admin direct-chat flow with getRoomUserIdsMap(List<ChatRoom>) that groups userId lists per room, introduced findNonAdminUserFromIds(List<Integer>, Map<Integer,User>), and updated getAdminDirectChatRooms to use IDs instead of ChatRoomMember entities.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I hopped through rows of id and room,
I left the heavy users to their gloom.
With nimble paws and ears alert,
I paired each chat with a lighter skirt.
Hooray — less baggage, quicker zoom!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is in Korean and references 'Join Fetch' and 'persistence context issues', which directly relates to the changes: a new repository method avoiding JOIN FETCH and a service method that uses it to prevent persistence context problems.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/chat-room-opponent-name

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

관리자 다이렉트 채팅방 목록 조회 시 JOIN FETCH로 인해 발생하던 영속성 컨텍스트 관련 문제를 줄이기 위해, 채팅방 멤버 조회에서 User를 fetch join 하지 않도록 조회 방식을 분리한 PR입니다.

Changes:

  • 관리자 다이렉트 채팅방 요약 조회에서 멤버 조회를 fetch join user 없는 쿼리로 변경
  • ChatRoomMemberRepositoryJOIN 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 메서드 추가

Comment on lines +729 to +737
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));
}
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getRoomMembersMap()getRoomMembersMapWithoutUser()가 로직이 거의 동일해서(빈 리스트 처리/roomIds 추출/groupingBy) 중복이 생깁니다. 공통 메서드로 추출하고 repository 호출만 주입(예: Function<List, List>)받도록 정리하면 향후 조회 방식이 늘어날 때 유지보수가 쉬워집니다.

Copilot uses AI. Check for mistakes.
FROM ChatRoomMember crm
WHERE crm.id.chatRoomId IN :chatRoomIds
""")
List<ChatRoomMember> findByChatRoomIdsWithoutUser(@Param("chatRoomIds") List<Integer> chatRoomIds);
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

findByChatRoomIdsWithoutUser는 실제로는 “user를 제외”하는 게 아니라 JOIN FETCH crm.user를 하지 않는 조회라서, 이름만 보면 의미가 모호할 수 있습니다. 기존 findByChatRoomIds가 fetch join을 포함하고 있으니, 메서드명을 ...FetchUser/...WithoutFetch처럼 의도를 더 직접적으로 드러내거나(또는 기본 메서드를 non-fetch로 두고 fetch 메서드를 별도 명명) 혼동을 줄이는 편이 안전합니다.

Suggested change
List<ChatRoomMember> findByChatRoomIdsWithoutUser(@Param("chatRoomIds") List<Integer> chatRoomIds);
List<ChatRoomMember> findByChatRoomIdsWithoutFetch(@Param("chatRoomIds") List<Integer> chatRoomIds);

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +62
@Query("""
SELECT crm
FROM ChatRoomMember crm
WHERE crm.id.chatRoomId IN :chatRoomIds
""")
List<ChatRoomMember> findByChatRoomIdsWithoutUser(@Param("chatRoomIds") List<Integer> chatRoomIds);
Copy link

Copilot AI Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 사용처(관리자 다이렉트 룸 요약)에서는 chatRoomId/userId만 필요합니다. 그런데 findByChatRoomIdsWithoutUserChatRoomMember 엔티티를 그대로 반환하면 결과가 영속성 컨텍스트에 적재/더티체킹 대상이 될 수 있으니, 가능하면 (chatRoomId, userId)만 담는 프로젝션/DTO 조회로 바꾸면 메모리·영속성 컨텍스트 부담을 더 줄일 수 있습니다.

Copilot uses AI. Check for mistakes.
@JanooGwan JanooGwan merged commit d76e72a into develop Feb 20, 2026
1 of 2 checks passed
@dh2906 dh2906 deleted the fix/chat-room-opponent-name branch February 22, 2026 05:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

버그 정상적으로 동작하지 않는 문제 상황 관련 이슈입니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants