Skip to content

[FEAT] 알림 도메인 api 구현 - #54

Merged
rkdehdrbs7885-oss merged 12 commits into
developfrom
feat/#34-notification-api
Jul 28, 2026
Merged

[FEAT] 알림 도메인 api 구현#54
rkdehdrbs7885-oss merged 12 commits into
developfrom
feat/#34-notification-api

Conversation

@rkdehdrbs7885-oss

@rkdehdrbs7885-oss rkdehdrbs7885-oss commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

📍 개요

알림 도메인 api 구현

⛓️‍💥 관련 이슈


🛠️ 작업 내용

  • 읽음 처리
  • 전체 읽음 처리
  • 알림 리스트 조회
  • 읽지 않은 알림 여부 확인
  • 알림 이벤트와 리스너

🔥 리뷰 요청 사항

리뷰어가 중점적으로 확인해주었으면 하는 내용을 작성해주세요.

  • 예외 코드 처리 방식

✅ 체크리스트

  • 코드 컨벤션을 준수했습니다.
  • 불필요한 코드 및 import를 제거했습니다.
  • 예외 처리를 적용했습니다.
  • 테스트를 완료했습니다.
  • 관련 Issue를 연결했습니다.

📎 참고 사항

Summary by CodeRabbit

Summary

  • 새로운 기능
    • 알림을 목록(페이지 단위)으로 확인할 수 있습니다.
    • 개별 알림 및 전체 알림을 읽음 처리할 수 있습니다.
    • 미읽음 알림 존재 여부를 확인할 수 있습니다.
    • 분석/연습/학습 활동 완료 시 알림이 자동으로 생성됩니다.
  • 개선 사항
    • 알림 중복 생성을 방지합니다.
    • 알림 목록에 제목/내용/읽음 상태/생성 시간이 표시됩니다.
    • 권한이 없는 접근 또는 존재하지 않는 알림에 대해 안내합니다.

@rkdehdrbs7885-oss rkdehdrbs7885-oss linked an issue Jul 25, 2026 that may be closed by this pull request
6 tasks
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

알림 엔티티의 사용자 연관관계와 생성 검증이 추가되었고, 이벤트 기반 저장·중복 방지·재시도와 사용자별 조회·읽음 처리 API가 구현되었다.

Changes

알림 기능

Layer / File(s) Summary
알림 모델과 응답 계약
src/main/java/com/mr/domain/notification/entity/Notification.java, src/main/java/com/mr/global/event/NotificationEvent.java, src/main/java/com/mr/domain/notification/dto/res/*
NotificationUser 연관관계를 사용하고 생성 시 입력값을 검증한다. 이벤트 팩토리와 단건·목록 응답 DTO가 추가되었다.
알림 저장소와 서비스 처리
src/main/java/com/mr/domain/notification/repository/NotificationRepository.java, src/main/java/com/mr/domain/notification/service/NotificationService.java, src/main/java/com/mr/domain/notification/exception/NotificationErrorStatus.java
사용자별 페이징 조회, 단건 조회, 전체 읽음 처리, 미읽음 확인과 중복 알림 확인이 제공된다. 서비스는 소유권 검증과 알림 상태 갱신을 처리한다.
이벤트 기반 알림 저장
src/main/java/com/mr/domain/notification/service/NotificationEventListener.java, build.gradle, src/main/java/com/mr/Application.java
커밋 이후 이벤트를 비동기로 처리하고, 최근 중복 확인과 사용자 조회 후 알림을 저장하며 실패 시 최대 3회 재시도한다.
인증 기반 알림 엔드포인트
src/main/java/com/mr/domain/notification/controller/NotificationController.java
알림 목록 조회, 개별·전체 읽음 처리와 미읽음 상태 확인 API를 인증 사용자 기준으로 노출한다.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant NotificationEvent
  participant NotificationEventListener
  participant UserRepository
  participant NotificationRepository
  NotificationEvent->>NotificationEventListener: 커밋 후 비동기 이벤트 전달
  NotificationEventListener->>NotificationRepository: 최근 동일 알림 확인
  NotificationEventListener->>UserRepository: 사용자 조회
  NotificationEventListener->>NotificationRepository: 알림 생성 및 저장
  NotificationRepository-->>NotificationEventListener: 저장 결과 또는 예외
Loading

Possibly related PRs

  • Musereview/BE#24: Notification 엔티티를 추가했으며, 이번 변경에서 사용자 매핑과 생성 로직이 확장되었다.

Poem

알림이 살며시 도착해
중복 문지기는 길을 지키고
실패하면 다시 도전해
읽음 표시에 마음 놓네
똑똑, 새 소식이다 🔔

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning 읽음/목록 API 외에 전체 읽음, 미읽음 상태, 이벤트 리스너, 재시도 설정과 엔티티 매핑 변경은 #34 범위를 벗어납니다. 추가 알림 기능과 인프라 변경은 별도 PR로 분리하거나 링크된 이슈에 범위를 명시해 주세요.
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 제목이 알림 도메인 API 구현이라는 핵심 변경을 짧고 명확하게 요약합니다.
Linked Issues check ✅ Passed 이슈 #34의 목록 조회, 단건 읽음 처리, DTO, 서비스/리포지토리, 권한 검증, 예외 처리가 모두 반영됐습니다.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/#34-notification-api

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/java/com/mr/domain/notification/repository/NotificationRepository.java`:
- Line 13: Update the NotificationRepository method name from
findAllByUserIdAndDeletedAtIsNull to use the nested User.userId property,
specifically findAllByUserUserIdAndDeletedAtIsNull, while preserving its
existing parameters and return type.

In `@src/main/java/com/mr/domain/notification/service/NotificationService.java`:
- Around line 28-30: Update readNotification to retrieve the notification
through a repository query that requires deletedAt to be null, instead of using
findById. Preserve the existing NOTIFICATION_NOT_FOUND exception so soft-deleted
notifications are rejected before markAsRead() runs.
- Around line 21-23: Update NotificationService.getNotificationList to call the
repository method using the nested Notification.user.userId property, renaming
findAllByUserIdAndDeletedAtIsNull to findAllByUserUserIdAndDeletedAtIsNull or
its underscore-delimited equivalent, and keep the existing deletedAt filter and
pagination behavior unchanged.
🪄 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: CHILL

Plan: Pro Plus

Run ID: 2e5dbdf5-cc2e-485f-88d0-94babc3e1bff

📥 Commits

Reviewing files that changed from the base of the PR and between a5ff3a9 and ac3429e.

📒 Files selected for processing (7)
  • src/main/java/com/mr/domain/notification/controller/NotificationController.java
  • src/main/java/com/mr/domain/notification/dto/res/NotificationDTO.java
  • src/main/java/com/mr/domain/notification/dto/res/NotificationListDTO.java
  • src/main/java/com/mr/domain/notification/entity/Notification.java
  • src/main/java/com/mr/domain/notification/exception/NotificationErrorStatus.java
  • src/main/java/com/mr/domain/notification/repository/NotificationRepository.java
  • src/main/java/com/mr/domain/notification/service/NotificationService.java

Comment thread src/main/java/com/mr/domain/notification/repository/NotificationRepository.java Outdated
Comment thread src/main/java/com/mr/domain/notification/service/NotificationService.java Outdated

@p1001q p1001q left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

💡 참고

  • src/main/java/com/mr/domain/notification/dto/res/NotificationListDTO.javaPage<Notification>을 씁니다(getTotalPages(), getTotalElements()). 팀 컨벤션(docs/컨벤션.md "목록 조회는 Page 대신 Slice를 우선 고려한다")상 PageCOUNT(*) 쿼리가 추가로 나가는데, 응답 DTO에 totalPage/totalElements가 실제로 프론트에서 쓰이는 값이면(페이지 번호 UI 등) Page가 맞는 선택이고 문제없습니다. 다만 "더보기"/무한스크롤 방식이라면 Slice로 바꾸는 게 더 저렴합니다 — 프론트 쪽에 페이지 번호 UI가 있는지만 확인하고 넘어가면 될 것 같아요.
  • NotificationDTO/NotificationListDTO 네이밍이 다른 도메인 예시(LearningProgressResponseDTO 등)의 Xxx**Response**DTO 접미사와 다릅니다. 강제 규칙은 아니라 blocking 사유는 아니고, 통일성 차원에서 참고만 해주세요.

Comment thread src/main/java/com/mr/domain/notification/entity/Notification.java

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
src/test/java/com/mr/domain/notification/service/NotificationServiceTest.java (1)

69-74: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

알림 미존재 예외 케이스도 추가해야 합니다.

NotificationService.readNotificationfindByIdAndDeletedAtIsNull(...)가 비어 있으면 NOTIFICATION_NOT_FOUND를 던지는 계약인데, 현재 테스트는 성공과 권한 없음만 검증합니다. Optional.empty()를 반환하는 경우 GeneralException과 정확한 오류 상태가 유지되는지 고정하세요.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/mr/domain/notification/service/NotificationServiceTest.java`
around lines 69 - 74, NotificationServiceTest의 readNotification 테스트에 알림 미존재 케이스를
추가하세요. notificationRepository.findByIdAndDeletedAtIsNull(...)가 Optional.empty()를
반환하도록 설정하고, NotificationService.readNotification이 GeneralException을 던지는지와 예외의 오류
상태가 NOTIFICATION_NOT_FOUND인지 검증하세요.
src/test/java/com/mr/domain/notification/controller/NotificationControllerTest.java (1)

63-72: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

서비스 호출 인자를 검증해 인증 계약을 고정하세요.

현재 테스트는 대부분 응답의 성공 여부만 확인합니다. 특히 doNothing()은 호출되지 않아도 기본적으로 통과할 수 있으므로, 잘못된 userIdnotificationId가 전달되어도 회귀를 잡지 못합니다. 각 테스트에서 verify(...)로 서비스 호출을 검증하고, 목록 조회에서는 Pageable의 page/size도 확인하세요.

Also applies to: 79-86, 93-100, 107-115

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/test/java/com/mr/domain/notification/controller/NotificationControllerTest.java`
around lines 63 - 72, Update the NotificationControllerTest cases around
notificationService calls to verify each service invocation with verify(...),
including tests using doNothing(). For the list retrieval test, verify the
expected userId and assert the passed Pageable has page 0 and size 10; apply
equivalent argument verification to the notification creation, read, and
deletion cases using their expected userId and notificationId values.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/test/java/com/mr/domain/notification/controller/NotificationControllerTest.java`:
- Around line 41-50: Update the MockMvc request setup in
NotificationControllerTest so each protected API request explicitly receives the
test SecurityContext via
SecurityMockMvcRequestPostProcessors.securityContext(...) or an equivalent
`@WithSecurityContext` configuration, ensuring `@AuthenticationPrincipal` resolves
the mocked user. If retaining the `@BeforeEach` SecurityContextHolder setup, clear
it after each test with SecurityContextHolder.clearContext().
- Line 44: NotificationControllerTest의 mockUserDetails 초기화에서 사용하는 mock 메서드가
컴파일되도록 org.mockito.Mockito.mock 정적 import를 추가하세요.

In
`@src/test/java/com/mr/domain/notification/service/NotificationServiceTest.java`:
- Around line 57-58: Update the fixture in NotificationServiceTest around
findAllByUser_UserIdAndDeletedAtIsNull to construct and return a
Page<Notification>, such as a PageImpl, instead of a SliceImpl. Keep the
existing notification, pageRequest, and non-final-page setup while matching the
repository and NotificationService Page<Notification> contract.

---

Nitpick comments:
In
`@src/test/java/com/mr/domain/notification/controller/NotificationControllerTest.java`:
- Around line 63-72: Update the NotificationControllerTest cases around
notificationService calls to verify each service invocation with verify(...),
including tests using doNothing(). For the list retrieval test, verify the
expected userId and assert the passed Pageable has page 0 and size 10; apply
equivalent argument verification to the notification creation, read, and
deletion cases using their expected userId and notificationId values.

In
`@src/test/java/com/mr/domain/notification/service/NotificationServiceTest.java`:
- Around line 69-74: NotificationServiceTest의 readNotification 테스트에 알림 미존재 케이스를
추가하세요. notificationRepository.findByIdAndDeletedAtIsNull(...)가 Optional.empty()를
반환하도록 설정하고, NotificationService.readNotification이 GeneralException을 던지는지와 예외의 오류
상태가 NOTIFICATION_NOT_FOUND인지 검증하세요.
🪄 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: CHILL

Plan: Pro Plus

Run ID: 08b10661-c251-4839-9b52-dc4cc5034243

📥 Commits

Reviewing files that changed from the base of the PR and between 716187b and 1bde744.

📒 Files selected for processing (2)
  • src/test/java/com/mr/domain/notification/controller/NotificationControllerTest.java
  • src/test/java/com/mr/domain/notification/service/NotificationServiceTest.java

Comment thread src/test/java/com/mr/domain/notification/service/NotificationServiceTest.java Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@src/main/java/com/mr/domain/notification/service/NotificationEventListener.java`:
- Around line 28-31: Update NotificationEventListener.handleNotificationEvent to
add a durable retry or recovery path for failures during findById/save, such as
an outbox or external queue, and record failure metrics or equivalent tracking.
Ensure retries are idempotent so repeated notification events do not create
inconsistent or duplicate records, while preserving the existing post-commit
asynchronous flow.
- Around line 33-49: Replace the time-and-title duplicate check in
NotificationEventListener with event-identity-based idempotency: add a unique
event ID to NotificationEvent, persist it on Notification, and enforce a
database UNIQUE constraint or unique index on (user_id, event_id). Update the
notification save flow to use UPSERT semantics so concurrent deliveries create
at most one record, handling the duplicate-key outcome without creating another
notification.
🪄 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: CHILL

Plan: Pro Plus

Run ID: 68cc8df8-3839-4169-87b4-d072079c91e9

📥 Commits

Reviewing files that changed from the base of the PR and between 1bde744 and aaf151b.

📒 Files selected for processing (3)
  • src/main/java/com/mr/domain/notification/repository/NotificationRepository.java
  • src/main/java/com/mr/domain/notification/service/NotificationEventListener.java
  • src/main/java/com/mr/global/event/NotificationEvent.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/mr/domain/notification/repository/NotificationRepository.java

@ownue ownue changed the title [Feat] 알림 도메인 api 구현 [FEAT] 알림 도메인 api 구현 Jul 26, 2026
@rkdehdrbs7885-oss
rkdehdrbs7885-oss requested a review from p1001q July 26, 2026 09:44

@p1001q p1001q left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

수정하시느라 수고하셨습니다!

@kimyw1018 kimyw1018 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

수고 하셨습니다!! 리뷰 확인해주세요~
승인 해두겠습니다

Comment thread src/main/java/com/mr/domain/notification/repository/NotificationRepository.java Outdated
@rkdehdrbs7885-oss
rkdehdrbs7885-oss merged commit 46fdbdf into develop Jul 28, 2026
2 checks passed
@kimyw1018
kimyw1018 deleted the feat/#34-notification-api branch August 4, 2026 12:55
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.

✨ Feature - 알림 관련 API 구현

3 participants