Conversation
- push token, 채팅 알림 필터, 인앱 알림, SSE, Expo 발송 정책을 코드 기준으로 문서화 - 동아리 지원 알림의 inbox/SSE/push 후속 효과와 AFTER_COMMIT 이벤트 경계를 정리 - 문서 claim 중 token 형식 허용과 push token 없는 동아리 지원 알림 경로를 회귀 테스트로 고정
|
Warning Rate limit exceeded
Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 30 minutes and 47 seconds. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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 configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 Walkthrough워크스루알림 도메인을 위한 새로운 문서( 변경 사항
예상 코드 리뷰 노력🎯 2 (간단) | ⏱️ ~10 분 관련 가능성 있는 PR
추천 레이블
시
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
🧪 JaCoCo Coverage Report (Changed Files)
|
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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/test/java/gg/agit/konect/unit/domain/notification/service/NotificationServiceTest.java`:
- Around line 316-343: The test
sendClubApplicationNotificationKeepsInboxAndSseWhenPushTokenMissing only covers
APPROVED and doesn't assert SSE payload fields; update tests to enforce the
shared "no push token -> keep inbox+SSE" policy by either (A) renaming this
method to specifically indicate APPROVED and adding two new tests that call
notificationService.sendClubApplicationSubmittedNotification(...) and
sendClubApplicationRejectedNotification(...), each verifying
notificationInboxService.sendSse(eq(userId), argThat(dto ->
dto.getType()/getTitle()/getBody()/getPath() match expected values)) and that
expoPushClient.sendNotification is never called, or (B) extend this single test
to loop over the three flows (SUBMITTED/APPROVED/REJECTED) invoking the
corresponding service methods and asserting SSE was sent with correct
NotificationInboxResponse payload fields and no push call; refer to
sendClubApplicationApprovedNotification,
sendClubApplicationSubmittedNotification,
sendClubApplicationRejectedNotification, notificationInboxService.sendSse,
expoPushClient.sendNotification and NotificationInboxResponse to locate and
implement the assertions.
🪄 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: cea68e37-8ebd-419d-8eb5-7b3855a347a5
📒 Files selected for processing (2)
src/main/java/gg/agit/konect/domain/notification/AGENTS.mdsrc/test/java/gg/agit/konect/unit/domain/notification/service/NotificationServiceTest.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 (1)
**/*
⚙️ CodeRabbit configuration file
**/*: 공통 리뷰 톤 가이드:
- 모든 코멘트는 첫 줄에
[LEVEL: ...]태그를 포함한다.- 과장된 표현 없이 사실 기반으로 작성한다.
- 한 코멘트에는 하나의 이슈만 다룬다.
- 코드 예시가 필요하면 최소 수정 예시를 제시한다.
- 가독성/단순화/확장성 이슈를 발견하면 우선순위를 높여 코멘트한다.
Files:
src/test/java/gg/agit/konect/unit/domain/notification/service/NotificationServiceTest.javasrc/main/java/gg/agit/konect/domain/notification/AGENTS.md
🧠 Learnings (9)
📓 Common learnings
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: 알림 도메인을 수정할 때는 push token, 인앱 알림 저장, SSE 전달, 채팅방 접속/뮤트 필터, 이벤트 commit 이후 발송이 함께 맞는지 항상 먼저 확인해야 한다.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: Push token 정책을 바꿀 때는 `notification_device_token.user_id` unique 제약, Expo token 정규식, 기존 token 갱신과 신규 저장 분기, 삭제 요청의 userId/token 일치 기준, 탈퇴 사용자 token 조회 제외 여부를 함께 확인해야 한다.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: 채팅 알림을 바꿀 때는 `ChatPresenceService` 접속 상태 필터, `NotificationMuteSetting`의 `CHAT_ROOM` mute 필터, 발신자 제외 정책, Unicode code point 기준 preview 길이, payload path, 예외를 삼키고 로그로 남기는 비동기 경계를 함께 확인해야 한다.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: 동아리 지원 알림을 바꿀 때는 동아리 이벤트 발행 시점, `AFTER_COMMIT` 리스너 유지 여부, inbox type/title/body/path, SSE 전송 대상과 응답 DTO, push token이 없을 때 인앱 알림을 유지하는 정책을 함께 확인해야 한다.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: 인앱 알림함을 바꿀 때는 채팅 관련 타입 제외 집합(`CHAT_MESSAGE`, `GROUP_CHAT_MESSAGE`, `UNREAD_CHAT_COUNT`), page size 20, `createdAt DESC, id DESC` 정렬, 단건 읽음의 userId 소유권 조건, 전체 읽음에서 채팅 관련 타입 제외를 함께 확인해야 한다.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: SSE를 바꿀 때는 사용자별 emitter 교체 정책, completion/timeout/error callback의 조건부 제거, 최초 connect 이벤트, send 실패 시 emitter 제거, 이미 완료된 emitter 처리를 함께 확인해야 한다.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: Expo push client를 바꿀 때는 batch size 100, channel id `default_notifications`, 2xx 상태와 body/data 검증, ticket별 실패 로그, retry/recover 메서드 시그니처를 함께 확인해야 한다.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: 동아리 이벤트 리스너를 바꿀 때는 동아리 도메인의 이벤트 발행 시점과 트랜잭션 경계를 함께 확인해야 한다.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: NotificationService는 push token 등록/삭제, 채팅 push, 동아리 지원 알림 발송을 담당하고, presence, mute, token 조회, inbox 저장, SSE, Expo push가 만나는 중심 서비스이다.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: NotificationInboxService는 인앱 알림 저장, 목록 조회, 미읽음 개수, 읽음 처리를 담당하고, 채팅 관련 알림을 알림함 목록/카운트/전체 읽음에서 제외하는 정책을 적용해야 한다.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: NotificationInboxSseService는 사용자별 SSE emitter 생명주기를 관리하고, 같은 사용자 재구독, connect 이벤트, 실패 시 emitter 제거 정책을 바꾸면 이 클래스를 먼저 확인해야 한다.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: ExpoPushClient는 Expo push API 호출, batch 분할, retry/recover, ticket 실패 로그를 담당하고, 외부 API 실패를 비즈니스 알림 흐름과 어떻게 분리할지 판단하는 지점이다.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: ClubApplicationNotificationListener는 동아리 지원 이벤트를 commit 이후 알림 발송으로 연결하고, 동아리 도메인의 이벤트 payload가 바뀌면 이 리스너와 알림 path/body를 같이 확인해야 한다.
Learnt from: CR
Repo: BCSDLab/KONECT_BACK_END
Timestamp: 2026-04-25T06:24:19.730Z
Learning: SSE 실패는 인앱 알림 저장이나 push 발송 정책과 분리해서 생각해야 한다.
📚 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/notification/AGENTS.md
📚 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/notification/AGENTS.md
📚 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/notification/AGENTS.md
📚 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/notification/AGENTS.md
📚 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/**/{group,club}*.{ts,tsx} : When modifying group or club_group membership policy, ensure access permissions, member removal and kick policies, list visibility, and club membership synchronization remain consistent
Applied to files:
src/main/java/gg/agit/konect/domain/notification/AGENTS.md
📚 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/notification/AGENTS.md
📚 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/notification/AGENTS.md
📚 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/main/java/gg/agit/konect/domain/notification/AGENTS.md
🔇 Additional comments (2)
src/test/java/gg/agit/konect/unit/domain/notification/service/NotificationServiceTest.java (1)
121-137: [LEVEL: APPROVE] ExponentPushToken 형식 허용 회귀 테스트 적절합니다.
EXPO_PUSH_TOKEN_PATTERN이 두 prefix를 모두 받아들인다는 정책을 고정하는 테스트로, save 인자에argThat으로 토큰 문자열까지 검증해 형식별 분기 회귀를 막아줍니다.src/main/java/gg/agit/konect/domain/notification/AGENTS.md (1)
1-265: [LEVEL: APPROVE] 알림 도메인 정책 가이드 내용이 코드 및 학습 사항과 일치합니다.token 형식(라인 26), 토큰 부재 시 push 생략(라인 70/109), batch 100(라인 142), page size 20과 정렬(라인 121-122), 채팅 제외 타입 집합(라인 124),
AFTER_COMMIT처리(라인 113-114) 등 핵심 invariant이 제공된 코드 스니펫(NotificationService232-241, 268-272, 38-39 등) 및 retrieved learnings와 부합합니다. "수정 시 함께 확인해야 하는 것" 섹션도 도메인 변경 시 회귀를 검토하기 좋은 체크리스트로 구성되어 있습니다.
There was a problem hiding this comment.
Pull request overview
알림(Notification) 도메인에서 AI 작업 시 준수해야 할 정책(푸시 토큰, 인앱 알림, SSE, Expo 발송)을 코드 기준으로 문서화하고, 누락되기 쉬운 토큰 형식/푸시 토큰 부재 경로를 회귀 테스트로 보강하는 PR입니다.
Changes:
- 알림 도메인 정책/생명주기/테스트 기준을
AGENTS.md로 문서화 registerToken에서ExponentPushToken[...]형식 허용을 단위 테스트로 고정- 동아리 지원 승인 알림에서 푸시 토큰이 없을 때 push만 생략되고 SSE는 유지되는지 테스트 추가
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/test/java/gg/agit/konect/unit/domain/notification/service/NotificationServiceTest.java | Expo 토큰 형식/푸시 토큰 부재 시 동작에 대한 회귀 테스트 추가 |
| src/main/java/gg/agit/konect/domain/notification/AGENTS.md | 알림 도메인의 핵심 정책(토큰, 인앱 알림, SSE, Expo 발송)을 코드 기준으로 정리 |
- 동아리 지원 알림 3종에서 push token이 없어도 inbox 저장과 SSE payload가 유지되는지 검증 - 발송용 token 조회와 내 token 조회의 실패 정책을 문서에서 분리해 오해를 줄임 - 리뷰가 지적한 문서 claim과 테스트 커버리지 불일치를 회귀 테스트로 고정
Addressed in |
🔍 개요
🚀 주요 변경 내용
src/main/java/gg/agit/konect/domain/notification/AGENTS.md를 추가해 알림 도메인의 주요 정책, 생명주기, 테스트 기준을 문서화했습니다.NotificationServiceTest에ExponentPushToken[...]허용 테스트를 추가했습니다.💬 참고 사항
CI=true ./gradlew test --tests 'gg.agit.konect.unit.domain.notification.*' --tests 'gg.agit.konect.integration.domain.notification.*'git diff --check, push 전 hook의checkstyleMain및compileJava./gradlew checkstyleTest는 기존 test 파일 line length 위반으로 실패했으며, 이번 변경 파일에서 새로 발생한 위반은 없었습니다.✅ Checklist (완료 조건)