Skip to content

refactor: 메시지 조회 응답 조립 책임 분리#607

Merged
dh2906 merged 7 commits intodevelopfrom
refactor/chat-message-read-service-599
Apr 28, 2026
Merged

refactor: 메시지 조회 응답 조립 책임 분리#607
dh2906 merged 7 commits intodevelopfrom
refactor/chat-message-read-service-599

Conversation

@dh2906
Copy link
Copy Markdown
Contributor

@dh2906 dh2906 commented Apr 28, 2026

🔍 개요


🚀 주요 변경 내용

  • ChatMessageReadService를 추가해 direct, SYSTEM_ADMIN 문의방, club group, group 메시지 page 응답 조립을 담당하도록 이동
  • readAt 갱신과 presence 기록은 ChatService에 남겨 기존 조회 side effect 순서를 유지
  • ChatServiceTest가 새 read 서비스를 실제 객체로 타도록 테스트 구성을 갱신

💬 참고 사항

  • checkstyleTest는 기존 테스트 파일의 120자 초과 위반 12건으로 실패합니다. 이번 변경 파일에서는 신규 위반이 없습니다.

✅ Checklist (완료 조건)

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

- ChatService에 남아 있던 direct, SYSTEM_ADMIN, club group, group 메시지 응답 조립을 ChatMessageReadService로 이동
- readAt 갱신과 presence 기록 순서는 기존 서비스 흐름에 남겨 조회 side effect 순서를 유지
- 메시지 조회 단위/통합 테스트를 재실행해 가시 범위와 페이징 응답 동작을 보존
@dh2906 dh2906 added the 리팩토링 리팩터링을 위한 이슈입니다. label Apr 28, 2026
@dh2906 dh2906 self-assigned this Apr 28, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

Warning

Rate limit exceeded

@dh2906 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 45 minutes and 39 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 515c73cf-eb30-4899-a832-be124ce0b8d9

📥 Commits

Reviewing files that changed from the base of the PR and between d748c01 and 2f9e6b6.

📒 Files selected for processing (3)
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
📝 Walkthrough

Walkthrough

채팅 메시지 조회 응답 조립 책임을 별도의 ChatMessageReadService로 분리하고, ChatService.getMessages(...)는 해당 서비스로 조회를 위임하도록 변경했습니다. 각 방 타입별(Direct, Admin/System-Direct, Club, Group) 페이징·unread 계산·sender 처리 로직이 이동했습니다.

Changes

Cohort / File(s) Summary
메시지 조회 서비스 신규 추가
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
Direct, Admin/System-direct, Club, Group 방별로 메시지 페이지 응답을 조립하는 4개 공개 메서드 추가. 가시 범위 계산(visibleMessageFrom), 멤버별 read baseline 정렬, binary search 기반 unreadCount 계산, admin sender 마스킹 및 isMine/isRead 판단 등을 구현.
기존 서비스 위임 처리
src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
getMessages(...)의 메시지 조회 분기를 새 ChatMessageReadService 호출로 대체(기존 lastRead 갱신·presence 기록 로직은 유지).
테스트 의존성 주입
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
테스트 setUp에서 ChatMessageReadService 인스턴스를 생성해 ChatService에 주입하도록 변경(테스트 와이어링 업데이트).

Sequence Diagram(s)

sequenceDiagram
    actor Client
    participant ChatService
    participant ChatMessageReadService
    participant Repo as MessageRepository
    participant Access as ChatDirectRoomAccessService

    Client->>ChatService: getMessages(request)
    ChatService->>ChatMessageReadService: request with user, room, page, limit
    alt direct room
        ChatMessageReadService->>Access: resolve visibleMessageFrom(user, room)
    end
    ChatMessageReadService->>Repo: query messages (page, limit, visibleMessageFrom?)
    ChatMessageReadService->>Repo: query room members / lastRead timestamps
    ChatMessageReadService->>ChatMessageReadService: build sorted read baselines, compute unreadCount (binary search)
    ChatMessageReadService->>ChatService: return ChatMessagePageResponse
    ChatService->>Client: return response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 내가 토끼라서 전하네,
새 서비스로 메시지 줄이 늘어났네,
직접·관리·클럽·그룹, 모두 정리했지,
바운더리와 읽음 계산, 깔끔히 챙겼지,
당근 한 입에 축하를! 🥕✨

🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 변경 내용의 핵심을 정확히 반영하고 있습니다: ChatService에서 ChatMessageReadService로 메시지 조회 응답 조립 책임을 분리했다는 점을 명확히 표현하고 있습니다.
Description check ✅ Passed PR 설명이 변경 사항과 관련 있으며, 개요, 주요 변경 내용, 참고 사항, 체크리스트를 포함하여 구체적이고 명확하게 작성되었습니다.
Linked Issues check ✅ Passed PR은 #599의 모든 주요 목표를 충족합니다: ChatMessageReadService 추가로 응답 조립 책임 분리, direct/SYSTEM_ADMIN/club/group 응답 정책 유지, readAt 갱신과 presence 기록을 ChatService에 유지, 테스트 업데이트 완료.
Out of Scope Changes check ✅ Passed 모든 변경 사항이 #599에서 요구한 메시지 조회 응답 조립 책임 분리 목표와 직접적으로 관련되어 있으며, 범위를 벗어난 변경 사항이 없습니다.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/chat-message-read-service-599

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.

❤️ Share

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

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 28, 2026

🧪 JaCoCo Coverage Report (Changed Files)

Summary

  • Overall Coverage: 90.0% ✅
  • Covered Lines: 433 / 481
  • Changed Files: 2

Coverage by File

Class Coverage Lines Status
ChatService
gg.agit.konect.domain.chat.service
86.5% 302/349
ChatMessageReadService
gg.agit.konect.domain.chat.service
99.2% 131/132

📊 View Workflow Run

Copy link
Copy Markdown
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

ChatService에 남아 있던 “메시지 조회 응답 조립” 로직을 별도 서비스(ChatMessageReadService)로 분리해, 조회 부수효과(readAt 갱신/presence 기록)는 ChatService에 유지하면서 응답 조립 책임을 정리한 PR입니다.

Changes:

  • 메시지 조회 응답 조립 로직을 ChatMessageReadService로 이동(direct / SYSTEM_ADMIN 문의방 / club group / group)
  • ChatService.getMessages()에서 신규 read 서비스로 위임하도록 연결
  • ChatServiceTest에서 신규 read 서비스를 실제 객체로 구성하도록 세팅 변경

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
src/main/java/gg/agit/konect/domain/chat/service/ChatService.java getMessages에서 응답 조립 로직을 ChatMessageReadService로 위임하도록 변경
src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java 메시지 페이지 응답 조립 책임을 담당하는 신규 서비스 추가
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java ChatService 생성 시 ChatMessageReadService를 실제 객체로 주입하도록 테스트 구성 변경

Comment thread src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java Outdated
dh2906 added 3 commits April 28, 2026 11:24
- develop에 병합된 초대/메시지 전송 책임 분리 변경을 메시지 조회 책임 분리 브랜치에 반영
- direct 메시지 조회 중 방 복원이 커밋되도록 getDirectChatRoomMessages를 쓰기 트랜잭션으로 고정
- SYSTEM_ADMIN 마스킹 판단에서 이미 조회한 room members를 재사용해 중복 멤버 조회를 제거
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java (1)

153-177: ⚠️ Potential issue | 🟠 Major

[LEVEL: medium] 새 읽기 서비스로 이동한 핵심 응답 규칙의 회귀 테스트가 빠져 있습니다.

문제: ChatMessageReadService를 주입만 하고 이번 PR에서 이동한 문의방 sender masking, visibleMessageFrom, unreadCount 집계 규칙을 직접 검증하는 테스트가 없습니다. 영향: 응답 조립이 바뀌어도 현재 테스트는 readAt/presence 호출 위주로만 확인해 메시지 노출 정책 회귀를 놓칠 수 있습니다. 제안: 일반 사용자·관리자 각각의 문의방 조회 응답에 대해 masking, 가시 범위, unreadCount를 검증하는 케이스를 이 PR에 추가하세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java`
around lines 153 - 177, Add unit tests in ChatServiceTest that explicitly verify
the migrated read/visibility rules now enforced by ChatMessageReadService:
create two test cases (regular member and system admin) that set up a chat room
with messages from multiple senders, appropriate readAt/presence states and
unread events, then call the same ChatService API used in other tests (the room
fetch/response assembler invoked via chatService) and assert three things: (1)
sender masking behavior for inquiry-type rooms (masked vs unmasked depending on
role), (2) correct visibleMessageFrom window (messages outside the visibility
window are absent), and (3) unreadCount aggregation matches expected counts
based on readAt/presence; use ChatMessageReadService, ChatService, and existing
repositories/mocks to arrange the data and verify results so regressions in
masking/visibility/unreadCount are caught.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/java/gg/agit/konect/domain/chat/service/ChatService.java`:
- Around line 262-280: The ChatService still contains private message-assembly
methods for direct/SYSTEM_ADMIN/club/group which duplicate logic now in
ChatMessageReadService; remove those private assembly methods from ChatService
and fully delegate message response construction to ChatMessageReadService by
calling its methods (e.g., chatMessageReadService.getDirectChatRoomMessages,
getAdminSystemDirectChatRoomMessages, getClubMessagesByRoom,
getGroupMessagesByRoom) from getMessages(), and move/ensure the single
authoritative implementations of visibleMessageFrom, unreadCount and
SYSTEM_ADMIN handling exist in ChatMessageReadService so all callers use that
central logic; update any test or caller expectations to use the new centralized
behavior.

---

Outside diff comments:
In `@src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java`:
- Around line 153-177: Add unit tests in ChatServiceTest that explicitly verify
the migrated read/visibility rules now enforced by ChatMessageReadService:
create two test cases (regular member and system admin) that set up a chat room
with messages from multiple senders, appropriate readAt/presence states and
unread events, then call the same ChatService API used in other tests (the room
fetch/response assembler invoked via chatService) and assert three things: (1)
sender masking behavior for inquiry-type rooms (masked vs unmasked depending on
role), (2) correct visibleMessageFrom window (messages outside the visibility
window are absent), and (3) unreadCount aggregation matches expected counts
based on readAt/presence; use ChatMessageReadService, ChatService, and existing
repositories/mocks to arrange the data and verify results so regressions in
masking/visibility/unreadCount are caught.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: bd95be75-b1ab-4a40-b56a-6e75e0067555

📥 Commits

Reviewing files that changed from the base of the PR and between f663bc7 and b0bc90b.

📒 Files selected for processing (3)
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: coverage
  • GitHub Check: Analyze (java-kotlin)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.java

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.java: Java 코드에서 import로 해결할 수 있는 경우 FQCN(Full Qualified Class Name)을 사용하지 않도록 지적한다
JPA/QueryDSL 조회 변경 시 N+1, 잘못된 fetch join, count 쿼리 왜곡, pagination 깨짐, distinct 누락을 확인한다
권한 로직은 관리자 우회, 요청자와 대상자 관계, 클럽/채팅방/공지/일정의 소속 검증이 빠지지 않았는지 확인한다
soft delete, 탈퇴 사용자, 차단/제외 조건, 중복 제거가 필요한 조회에서는 응답에 노출되면 안 되는 데이터가 포함되는지 확인한다
DTO 응답 변경은 기존 클라이언트가 기대하는 필드명, nullability, enum/string 값, 정렬 순서를 깨지 않는지 확인한다
조건이 2개 이상 결합된 비즈니스 규칙, 권한 조건, soft delete 제외, 중복 제거, fallback 우선순위, 대표값 선택, DTO 변환, count 쿼리 분리, fetch join 선택 이유처럼 코드만으로 의도가 숨겨지는 지점에는 주석을 권장한다
단순 생성자 호출, 필드 매핑, 컬렉션 반환, 이름만으로 명확한 분기에는 주석을 요구하지 않는다

Files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
**/*.{sql,java}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

데이터베이스 변경에서는 마이그레이션 순서, 기존 데이터 호환성, nullable/default 처리, 롤백 난이도, 인덱스 필요성을 확인한다

Files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
**/*

⚙️ CodeRabbit configuration file

**/*: 공통 리뷰 톤 가이드:

  • 모든 코멘트는 첫 줄에 [LEVEL: ...] 태그를 포함한다.
  • 과장된 표현 없이 사실 기반으로 작성한다.
  • 한 코멘트에는 하나의 이슈만 다룬다.
  • 코드 예시가 필요하면 최소 수정 예시를 제시한다.
  • 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.

Files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
src/main/java/**/*.java

⚙️ CodeRabbit configuration file

src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.

  • 코멘트는 반드시 한국어로 작성한다.
  • 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
  • 각 코멘트 첫 줄에 심각도를 [LEVEL: high|medium|low] 형식으로 반드시 표기한다.
  • 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
  • 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
  • 가능하면 재현 조건 및 실패 시나리오도 포함한다.
  • 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
  • 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
  • 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
  • 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
  • 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.

Files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
🧠 Learnings (31)
📓 Common learnings
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message}/**/*.{ts,tsx} : When modifying message storage logic, verify that last message metadata, direct room restoration conditions, sender's read status updates, list summary sorting, inquiry room special handling, and notification/event side effects remain consistent
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Before modifying chat domain code, answer whether the change breaks direct's leave->restore->reopen policy, misaligns last message with unreadCount, exposes invisible messages, overgeneralizes direct/group policies, breaks SYSTEM_ADMIN reuse, leaks message existence info, or omits list metadata
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member}/**/*.{ts,tsx} : When modifying read status logic, ensure unreadCount calculation, direct room visibility range consistency, list badge and summary values, and inquiry room SYSTEM_ADMIN read status handling remain aligned
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,service}/**/chat.service.{ts,tsx} : Chat service must be the central point where message sending, list summaries, access handling, and membership changes interact, coordinating all state updates
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/{unread,count}*.{ts,tsx} : UnreadCount calculation for direct chat rooms must consider both lastReadAt and actual visible message range (visibleMessageFrom), not just lastReadAt alone
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,service}/**/chat.service.{ts,tsx} : Chat service must be the central point where message sending, list summaries, access handling, and membership changes interact, coordinating all state updates

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-25T06:58:54.393Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notification/AGENTS.md:0-0
Timestamp: 2026-04-25T06:58:54.393Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notification/**/*IntegrationTest*.java : Add regression tests for: club application event rollback resulting in zero notifications created (AFTER_COMMIT integration test), inbox list/unread count/bulk read excluding chat-related types (repository integration test), Expo push partial ticket failures logged without whole-request exception propagation, group chat token vs target user count mismatch in current policy.

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message}/**/*.{ts,tsx} : When modifying message storage logic, verify that last message metadata, direct room restoration conditions, sender's read status updates, list summary sorting, inquiry room special handling, and notification/event side effects remain consistent

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-25T06:58:54.393Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notification/AGENTS.md:0-0
Timestamp: 2026-04-25T06:58:54.393Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notification/**/*ChatPresenceService*.java : Chat presence service tracks which users are currently viewing specific chat rooms. During chat push notification sending, check presence state to exclude users already present in the target chatroom from receiving push notifications.

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,service}/**/chat-room-membership*.{ts,tsx} : ChatRoomMembershipService must handle club_group member guarantee, direct/group membership updates, inquiry room read status exceptions, and concurrent creation/duplicate membership absorption

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-25T06:58:54.393Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notification/AGENTS.md:0-0
Timestamp: 2026-04-25T06:58:54.393Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notification/**/*.java : When modifying chat notification logic, verify: ChatPresenceService presence filtering, NotificationMuteSetting CHAT_ROOM mute filtering, sender exclusion for group chat, Unicode code point basis (not Java string length) for 30-character preview limit, payload path format `chats/{roomId}`, and that exceptions are caught in async boundary.

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
📚 Learning: 2026-04-25T06:58:54.393Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notification/AGENTS.md:0-0
Timestamp: 2026-04-25T06:58:54.393Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notification/**/*.java : When modifying inbox functionality, verify: chat-related type exclusion set (`CHAT_MESSAGE`, `GROUP_CHAT_MESSAGE`, `UNREAD_CHAT_COUNT`), page size default of 20, sort order `createdAt DESC, id DESC`, userId ownership check for single read, and chat-type exclusion in bulk read operations.

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member}/**/*.{ts,tsx} : When modifying read status logic, ensure unreadCount calculation, direct room visibility range consistency, list badge and summary values, and inquiry room SYSTEM_ADMIN read status handling remain aligned

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,repository}/**/*.{ts,tsx} : Repository layer must implement optimized queries for latest message retrieval, unreadCount calculation, list optimization, and distinct handling of direct vs group list logic

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,list}/**/{list,summary}*.{ts,tsx} : Chat room list summaries must combine last message, last send time, unreadCount, room name, and mute status consistently without treating direct and group room construction separately

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,message}/**/{repository,query,list,search}*.{ts,tsx} : When modifying list/search queries, verify custom room name priority, mute status composition, search target room type scope, direct room visible message criteria, messageId page calculation sort consistency, and inquiry room list optimization query conditions remain correct

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/*{inquiry,admin,system}*.{ts,tsx} : Inquiry room (SYSTEM_ADMIN type) unreadCount and read status must be aggregated/updated by SYSTEM_ADMIN user record, not by individual admin users

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member}/**/chat-room-member*.{ts,tsx} : ChatRoomMember must maintain direct room visibility state (lastReadAt, visibleMessageFrom, leftAt, custom name, owner flag) with coordinated updates

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,list}/**/{query,construct,list}*.{ts,tsx} : Direct and group room types have fundamentally different list construction logic - direct uses chat_room.last_message_* directly while group/club_group combines latest message queries - these must not be unified into identical query paths

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,club,member}/**/*.{ts,tsx} : When club membership changes (add/remove), chat room membership must be synchronized to maintain consistent access guarantees for club_group rooms

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,message,search}/**/{list,summary,search}*.{ts,tsx} : Direct chat rooms must not expose invisible messages (based on visibleMessageFrom) in list summaries or search results

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,inquiry,admin,system}/**/{send,create}*.{ts,tsx} : Inquiry room (SYSTEM_ADMIN) message send by general admin must not add the admin as a room member and must use special handling

Applied to files:

  • src/test/java/gg/agit/konect/unit/domain/chat/service/ChatServiceTest.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/{unread,count}*.{ts,tsx} : UnreadCount calculation for direct chat rooms must consider both lastReadAt and actual visible message range (visibleMessageFrom), not just lastReadAt alone

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,direct}/**/{send,create}*.{ts,tsx} : Sending a message in a direct room must update the sender's lastReadAt to the new message timestamp and may restore the room visibility if the sender was in leftAt state

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,group,club}/**/{send,create}*.{ts,tsx} : Sending a message in group or club_group room must update the sender's read status (lastReadAt) immediately upon send

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,list,inquiry,admin}/**/*.{ts,tsx} : Admin inquiry room list must use separate optimized query returning only rooms where the admin has actually sent responses, distinct from regular direct list logic

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/chat/**/*{inquiry,admin,system}*.{ts,tsx} : SYSTEM_ADMIN inquiry room reuse policy (SYSTEM_ADMIN + regular user pair) must not be broken by adding general admins as room members

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/chat/**/*direct*member*.{ts,tsx} : When modifying direct membership policy, verify that leftAt, visibleMessageFrom, lastReadAt states, room re-exposure conditions, past message visibility range, search/message jump visibility, and list re-exposure conditions remain consistent

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-13T00:26:23.225Z
Learnt from: dh2906
Repo: BCSDLab/KONECT_BACK_END PR: 533
File: src/main/java/gg/agit/konect/domain/chat/service/ChatService.java:1511-1516
Timestamp: 2026-04-13T00:26:23.225Z
Learning: In ChatService.java (Spring Boot + JPA, MySQL InnoDB), within a `Transactional(readOnly = true)` method, retrying a repository count query (e.g., `countNewerMessagesByChatRoomId`) to handle concurrent inserts is ineffective under REPEATABLE READ isolation: the same DB snapshot is used throughout the transaction, so the retry always returns the same result. A new transaction (`Propagation.REQUIRES_NEW`) would be required for a true retry, but accepting a 1-page offset as a UX tradeoff is preferred for search navigation in this codebase.

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,direct}/**/{send,receive,create}*.{ts,tsx} : Direct room visibility may be restored when a new message arrives even if the receiving user has leftAt set

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/chat/**/*direct*member*.{ts,tsx} : Direct chat room states (leftAt, visibleMessageFrom, lastReadAt) must not be treated as independent values and must move together according to the leave->restore->reopen policy

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,direct}/**/*.{ts,tsx} : Direct chat room message visibility must be determined by visibleMessageFrom combined with leftAt status, not by simple member existence

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,member}/**/*.{ts,tsx} : The direct chat room leave->restore->reopen policy must not be generalized to group or club_group room types

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-25T07:51:26.474Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notice/AGENTS.md:0-0
Timestamp: 2026-04-25T07:51:26.474Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notice/**/*NoticeService.java : Notice detail endpoint GET /councils/notices/{id} must use a write transaction (not read-only) to enable read history creation

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,page,jump}/**/*.{ts,tsx} : MessageId page calculation must validate room access permission and message visibility range before calculating pagination position to prevent information disclosure

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java

Comment thread src/main/java/gg/agit/konect/domain/chat/service/ChatService.java
- members 기반 SYSTEM_ADMIN 포함 여부 판단은 유지하면서 반환 흐름만 한 줄로 정리
- 리뷰 반영 코드의 의도를 바꾸지 않고 중복 분기만 줄임
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java`:
- Around line 199-228: The unread baseline calculation currently uses only
ChatRoomMember::getLastReadAt (in toSortedReadBaselines and
toAdminChatReadBaselines), which causes stale messages to be counted for
direct/SYSTEM_ADMIN rooms; update both methods to compute each member's baseline
as the later of member.getLastReadAt() and member.getVisibleMessageFrom() (i.e.,
max(lastReadAt, visibleMessageFrom)) when forming the per-representative
baselines (keep the admin vs user separation in toAdminChatReadBaselines), then
sort and return those baselines so unreadCount honors actual visibleMessageFrom
ranges for direct chats.
- Around line 62-69: The code currently computes visibleMessageFrom using
resolveAdminSystemRoomVisibleMessageFrom (based on SYSTEM_ADMIN member) which
causes incorrect visibility for a requester who left and rejoined; change logic
in ChatMessageReadService so visibleMessageFrom is derived from the requesting
user's ChatRoomMember (use members.find by user id and consider that member's
visibleMessageFrom and leftAt) and pass that per-requester visibleMessageFrom
into buildDirectChatRoomMessages; retain
resolveAdminSystemRoomVisibleMessageFrom/toAdminChatReadBaselines and
getMaskedAdminId for unread/read aggregation only (i.e., use SYSTEM_ADMIN
baseline solely for aggregate counts, not for determining which messages the
requester may see).
- Around line 168-173: The isMine calculation incorrectly ties to maskedAdminId;
in ChatMessageReadService separate sender masking from ownership check: keep
senderId assignment using maskedAdminId and resolveDirectSenderId(message,
maskedAdminId), but compute isMine first as message.isSentBy(user.getId()), and
only override it with shouldDisplayAsOwnMessage(user, message, true) when this
is an admin-view scenario (i.e. maskedAdminId != null AND the current request is
an admin view — use the existing admin flag on the user/context if available);
update the same pattern where else-applied (the block referenced around 254-263)
so admin-only branching is used for shouldDisplayAsOwnMessage.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 53650a4f-3562-43a7-895e-9f837519a07c

📥 Commits

Reviewing files that changed from the base of the PR and between b0bc90b and d748c01.

📒 Files selected for processing (1)
  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: Code Style Check
  • GitHub Check: Analyze (java-kotlin)
  • GitHub Check: coverage
🧰 Additional context used
📓 Path-based instructions (4)
**/*.java

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.java: Java 코드에서 import로 해결할 수 있는 경우 FQCN(Full Qualified Class Name)을 사용하지 않도록 지적한다
JPA/QueryDSL 조회 변경 시 N+1, 잘못된 fetch join, count 쿼리 왜곡, pagination 깨짐, distinct 누락을 확인한다
권한 로직은 관리자 우회, 요청자와 대상자 관계, 클럽/채팅방/공지/일정의 소속 검증이 빠지지 않았는지 확인한다
soft delete, 탈퇴 사용자, 차단/제외 조건, 중복 제거가 필요한 조회에서는 응답에 노출되면 안 되는 데이터가 포함되는지 확인한다
DTO 응답 변경은 기존 클라이언트가 기대하는 필드명, nullability, enum/string 값, 정렬 순서를 깨지 않는지 확인한다
조건이 2개 이상 결합된 비즈니스 규칙, 권한 조건, soft delete 제외, 중복 제거, fallback 우선순위, 대표값 선택, DTO 변환, count 쿼리 분리, fetch join 선택 이유처럼 코드만으로 의도가 숨겨지는 지점에는 주석을 권장한다
단순 생성자 호출, 필드 매핑, 컬렉션 반환, 이름만으로 명확한 분기에는 주석을 요구하지 않는다

Files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
**/*.{sql,java}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

데이터베이스 변경에서는 마이그레이션 순서, 기존 데이터 호환성, nullable/default 처리, 롤백 난이도, 인덱스 필요성을 확인한다

Files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
src/main/java/**/*.java

⚙️ CodeRabbit configuration file

src/main/java/**/*.java: 아래 원칙으로 리뷰 코멘트를 작성한다.

  • 코멘트는 반드시 한국어로 작성한다.
  • 반드시 수정이 필요한 항목만 코멘트로 남기고, 단순 취향 차이는 지적하지 않는다.
  • 각 코멘트 첫 줄에 심각도를 [LEVEL: high|medium|low] 형식으로 반드시 표기한다.
  • 심각도 기준: high=운영 장애 가능, medium=품질 저하, low=개선 권고.
  • 각 코멘트는 "문제 -> 영향 -> 제안" 순서로 3문장 이내로 간결하게 작성한다.
  • 가능하면 재현 조건 및 실패 시나리오도 포함한다.
  • 제안은 현재 코드베이스(Spring Boot + JPA + Flyway) 패턴과 일치해야 한다.
  • 보안, 트랜잭션 경계, 예외 처리, N+1, 성능 회귀 가능성을 우선 점검한다.
  • 가독성: 변수/메서드 이름이 의도를 바로 드러내는지, 중첩과 메서드 길이가 과도하지 않은지 점검한다.
  • 단순화: 불필요한 추상화, 중복 로직, 과한 방어 코드가 있으면 더 단순한 대안을 제시한다.
  • 확장성: 새 요구사항 추가 시 변경 범위가 최소화되는 구조인지(하드코딩 분기/값 여부 포함) 점검한다.

Files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
**/*

⚙️ CodeRabbit configuration file

**/*: 공통 리뷰 톤 가이드:

  • 모든 코멘트는 첫 줄에 [LEVEL: ...] 태그를 포함한다.
  • 과장된 표현 없이 사실 기반으로 작성한다.
  • 한 코멘트에는 하나의 이슈만 다룬다.
  • 코드 예시가 필요하면 최소 수정 예시를 제시한다.
  • 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.

Files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
🧠 Learnings (26)
📓 Common learnings
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Before modifying chat domain code, answer whether the change breaks direct's leave->restore->reopen policy, misaligns last message with unreadCount, exposes invisible messages, overgeneralizes direct/group policies, breaks SYSTEM_ADMIN reuse, leaks message existence info, or omits list metadata
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,service}/**/chat.service.{ts,tsx} : Chat service must be the central point where message sending, list summaries, access handling, and membership changes interact, coordinating all state updates
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/*{inquiry,admin,system}*.{ts,tsx} : Inquiry room (SYSTEM_ADMIN type) unreadCount and read status must be aggregated/updated by SYSTEM_ADMIN user record, not by individual admin users
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member}/**/*.{ts,tsx} : When modifying read status logic, ensure unreadCount calculation, direct room visibility range consistency, list badge and summary values, and inquiry room SYSTEM_ADMIN read status handling remain aligned
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/{unread,count}*.{ts,tsx} : UnreadCount calculation for direct chat rooms must consider both lastReadAt and actual visible message range (visibleMessageFrom), not just lastReadAt alone
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message}/**/*.{ts,tsx} : When modifying message storage logic, verify that last message metadata, direct room restoration conditions, sender's read status updates, list summary sorting, inquiry room special handling, and notification/event side effects remain consistent
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,group,club}/**/{send,create}*.{ts,tsx} : Sending a message in group or club_group room must update the sender's read status (lastReadAt) immediately upon send
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notification/AGENTS.md:0-0
Timestamp: 2026-04-25T06:58:54.405Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notification/**/*.java : When modifying inbox functionality, verify: chat-related type exclusion set (`CHAT_MESSAGE`, `GROUP_CHAT_MESSAGE`, `UNREAD_CHAT_COUNT`), page size default of 20, sort order `createdAt DESC, id DESC`, userId ownership check for single read, and chat-type exclusion in bulk read operations.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,repository}/**/*.{ts,tsx} : Repository layer must implement optimized queries for latest message retrieval, unreadCount calculation, list optimization, and distinct handling of direct vs group list logic
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,service}/**/chat-room-membership*.{ts,tsx} : ChatRoomMembershipService must handle club_group member guarantee, direct/group membership updates, inquiry room read status exceptions, and concurrent creation/duplicate membership absorption
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/{unread,count}*.{ts,tsx} : UnreadCount calculation for direct chat rooms must consider both lastReadAt and actual visible message range (visibleMessageFrom), not just lastReadAt alone

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member}/**/*.{ts,tsx} : When modifying read status logic, ensure unreadCount calculation, direct room visibility range consistency, list badge and summary values, and inquiry room SYSTEM_ADMIN read status handling remain aligned

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,direct}/**/{send,create}*.{ts,tsx} : Sending a message in a direct room must update the sender's lastReadAt to the new message timestamp and may restore the room visibility if the sender was in leftAt state

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,group,club}/**/{send,create}*.{ts,tsx} : Sending a message in group or club_group room must update the sender's read status (lastReadAt) immediately upon send

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,message}/**/*{inquiry,admin,system}*.{ts,tsx} : Inquiry room (SYSTEM_ADMIN type) unreadCount and read status must be aggregated/updated by SYSTEM_ADMIN user record, not by individual admin users

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message}/**/*.{ts,tsx} : When modifying message storage logic, verify that last message metadata, direct room restoration conditions, sender's read status updates, list summary sorting, inquiry room special handling, and notification/event side effects remain consistent

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,service}/**/chat.service.{ts,tsx} : Chat service must be the central point where message sending, list summaries, access handling, and membership changes interact, coordinating all state updates

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,list}/**/{list,summary}*.{ts,tsx} : Chat room list summaries must combine last message, last send time, unreadCount, room name, and mute status consistently without treating direct and group room construction separately

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member}/**/chat-room-member*.{ts,tsx} : ChatRoomMember must maintain direct room visibility state (lastReadAt, visibleMessageFrom, leftAt, custom name, owner flag) with coordinated updates

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,member,service}/**/chat-room-membership*.{ts,tsx} : ChatRoomMembershipService must handle club_group member guarantee, direct/group membership updates, inquiry room read status exceptions, and concurrent creation/duplicate membership absorption

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-13T00:26:23.225Z
Learnt from: dh2906
Repo: BCSDLab/KONECT_BACK_END PR: 533
File: src/main/java/gg/agit/konect/domain/chat/service/ChatService.java:1511-1516
Timestamp: 2026-04-13T00:26:23.225Z
Learning: In ChatService.java (Spring Boot + JPA, MySQL InnoDB), within a `Transactional(readOnly = true)` method, retrying a repository count query (e.g., `countNewerMessagesByChatRoomId`) to handle concurrent inserts is ineffective under REPEATABLE READ isolation: the same DB snapshot is used throughout the transaction, so the retry always returns the same result. A new transaction (`Propagation.REQUIRES_NEW`) would be required for a true retry, but accepting a 1-page offset as a UX tradeoff is preferred for search navigation in this codebase.

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,direct}/**/{send,receive,create}*.{ts,tsx} : Direct room visibility may be restored when a new message arrives even if the receiving user has leftAt set

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/chat/**/*direct*member*.{ts,tsx} : When modifying direct membership policy, verify that leftAt, visibleMessageFrom, lastReadAt states, room re-exposure conditions, past message visibility range, search/message jump visibility, and list re-exposure conditions remain consistent

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/chat/**/*direct*member*.{ts,tsx} : Direct chat room states (leftAt, visibleMessageFrom, lastReadAt) must not be treated as independent values and must move together according to the leave->restore->reopen policy

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,direct}/**/*.{ts,tsx} : Direct chat room message visibility must be determined by visibleMessageFrom combined with leftAt status, not by simple member existence

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,member}/**/*.{ts,tsx} : The direct chat room leave->restore->reopen policy must not be generalized to group or club_group room types

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/chat/**/*{inquiry,admin,system}*.{ts,tsx} : SYSTEM_ADMIN inquiry room reuse policy (SYSTEM_ADMIN + regular user pair) must not be broken by adding general admins as room members

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,list,inquiry,admin}/**/*.{ts,tsx} : Admin inquiry room list must use separate optimized query returning only rooms where the admin has actually sent responses, distinct from regular direct list logic

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,inquiry,admin,system}/**/{send,create}*.{ts,tsx} : Inquiry room (SYSTEM_ADMIN) message send by general admin must not add the admin as a room member and must use special handling

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,room,message}/**/{repository,query,list,search}*.{ts,tsx} : When modifying list/search queries, verify custom room name priority, mute status composition, search target room type scope, direct room visible message criteria, messageId page calculation sort consistency, and inquiry room list optimization query conditions remain correct

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-25T07:51:26.486Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notice/AGENTS.md:0-0
Timestamp: 2026-04-25T07:51:26.486Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notice/**/*NoticeService.java : Notice detail endpoint GET /councils/notices/{id} must use a write transaction (not read-only) to enable read history creation

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-27T00:51:24.941Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/inquiry/AGENTS.md:0-0
Timestamp: 2026-04-27T00:51:24.941Z
Learning: 채팅 도메인의 SYSTEM_ADMIN 문의방 정책, 채팅방 reopen, 마지막 메시지 갱신 정책을 문의 도메인에 섞으면 안 된다

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,message,page,jump}/**/*.{ts,tsx} : MessageId page calculation must validate room access permission and message visibility range before calculating pagination position to prevent information disclosure

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-22T08:07:59.395Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/chat/AGENTS.md:0-0
Timestamp: 2026-04-22T08:07:59.395Z
Learning: Applies to src/main/java/gg/agit/konect/domain/chat/**/{chat,repository}/**/*.{ts,tsx} : Repository layer must implement optimized queries for latest message retrieval, unreadCount calculation, list optimization, and distinct handling of direct vs group list logic

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java
📚 Learning: 2026-04-25T06:58:54.405Z
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END PR: 0
File: src/main/java/gg/agit/konect/domain/notification/AGENTS.md:0-0
Timestamp: 2026-04-25T06:58:54.405Z
Learning: Applies to src/main/java/gg/agit/konect/domain/notification/**/*NotificationInboxService*.java : Inbox list retrieval: default page 1, page size 20, sort by `createdAt DESC, id DESC`. Exclude chat-related types (`CHAT_MESSAGE`, `GROUP_CHAT_MESSAGE`, `UNREAD_CHAT_COUNT`) from list queries, unread count queries, and bulk read operations. Single read operation only allows reading user's own notification; other users' notification ids are treated as not found. Bulk read operation only marks unread notifications of non-chat types as read.

Applied to files:

  • src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java

Comment thread src/main/java/gg/agit/konect/domain/chat/service/ChatMessageReadService.java Outdated
- ChatService에 남아 있던 메시지 응답 조립 메서드를 제거해 ChatMessageReadService가 단일 구현을 갖도록 정리
- 일반 사용자 문의방 조회에서도 관리자 발신자가 SYSTEM_ADMIN으로 보이도록 masking 기준을 read service에서 적용
- 일반 사용자와 관리자 문의방 조회 테스트로 가시 범위, unreadCount, sender 표시 정책 회귀를 막음
- 전체 테스트는 통과했으며 checkstyleTest는 기존 club/notification/chat 테스트 장문 라인 위반이 남아 있어 별도 정리가 필요함
@dh2906
Copy link
Copy Markdown
Contributor Author

dh2906 commented Apr 28, 2026

새 읽기 서비스로 이동한 핵심 응답 규칙의 회귀 테스트가 빠져 있습니다.

Addressed: ChatServiceTest에 일반 사용자/관리자 문의방 조회 케이스를 보강했습니다. 두 케이스 모두 ChatService.getMessages() 경로로 호출하고, visibleMessageFrom 기준 조회, sender 표시/마스킹, unreadCount, isMine 응답을 함께 검증합니다.

- direct 계열 메시지의 unread baseline을 lastReadAt 단독 기준에서 visibleMessageFrom을 함께 보는 기준으로 정리
- 나갔다가 복원된 멤버가 볼 수 없는 과거 메시지가 unreadCount에 포함되지 않도록 방지
- 문의방 조회 테스트에 visibleMessageFrom이 lastReadAt보다 늦은 멤버를 포함해 회귀를 검증
Copy link
Copy Markdown
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

Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.

@dh2906 dh2906 merged commit bdc749b into develop Apr 28, 2026
9 checks passed
@dh2906 dh2906 deleted the refactor/chat-message-read-service-599 branch April 28, 2026 05:45
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