Skip to content

[hotfix] 알림 읽음 처리 api 수정#313

Merged
seongjunnoh merged 1 commit into
developfrom
hotfix/#312-notification-check-api
Sep 24, 2025
Merged

[hotfix] 알림 읽음 처리 api 수정#313
seongjunnoh merged 1 commit into
developfrom
hotfix/#312-notification-check-api

Conversation

@seongjunnoh
Copy link
Copy Markdown
Collaborator

@seongjunnoh seongjunnoh commented Sep 24, 2025

#️⃣ 연관된 이슈

closes #312

📝 작업 내용

이슈 참고해 주시면 됩니다.

개발서버에서 제대로 동작하는것 확인했습니다

📸 스크린샷

💬 리뷰 요구사항

📌 PR 진행 시 이러한 점들을 참고해 주세요

* P1 : 꼭 반영해 주세요 (Request Changes) - 이슈가 발생하거나 취약점이 발견되는 케이스 등
* P2 : 반영을 적극적으로 고려해 주시면 좋을 것 같아요 (Comment)
* P3 : 이런 방법도 있을 것 같아요~ 등의 사소한 의견입니다 (Chore)

Summary by CodeRabbit

  • 신규 기능
    • 이미 읽은 알림을 다시 읽음 처리할 때, 성공(200)과 함께 리다이렉트 정보(route/params)를 반환합니다.
  • 버그 수정
    • 알림 읽음 처리 시 응답 구조를 일관되게 정리했습니다. 권한이 없는 경우 403은 그대로 유지됩니다.
  • 문서
    • API 설명을 보강하고, 불필요한 오류 사례를 정리해 문서 정확도를 높였습니다.
  • 테스트
    • 재읽기 시나리오를 성공 응답 검증으로 업데이트하고, 리다이렉트 데이터 검증을 추가했습니다.

- 이미 읽음 처리된 알림에 대한 요청을 받더라도 정상 응답 하도록 수정
@seongjunnoh seongjunnoh linked an issue Sep 24, 2025 that may be closed by this pull request
2 tasks
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Sep 24, 2025

Walkthrough

알림 읽음 처리 흐름을 수정했다. 이미 읽은 알림에 대해서 예외를 무시하고 리다이렉트 데이터로 응답하도록 서비스 로직을 변경했다. 스웨거 응답 설명과 컨트롤러 API 설명을 이에 맞게 조정했다. 관련 테스트는 에러 경로 제거 및 리다이렉트 데이터 검증으로 갱신했다.

Changes

Cohort / File(s) Summary
Swagger 응답 설명 정리
src/main/java/konkuk/thip/common/swagger/SwaggerResponseDescription.java
NOTIFICATION_MARK_TO_CHECKED의 에러 코드 세트에서 NOTIFICATION_ALREADY_CHECKED 제거. 이제 NOTIFICATION_NOT_FOUND, NOTIFICATION_ACCESS_FORBIDDEN만 포함.
컨트롤러 문서 설명 보강
src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java
"유저의 특정 알림 읽음 처리" 설명에 이미 읽은 경우 리다이렉트 데이터만 반환한다는 문구 추가. 로직/시그니처 변경 없음.
서비스 로직 예외 처리 변경
src/main/java/konkuk/thip/notification/application/service/NotificationMarkService.java
notification.markToChecked() 수행 시 InvalidStateException을 캐치하여 이미 읽은 상태면 예외를 무시하고 업데이트 생략. 성공 시에만 업데이트 수행. import 추가.
API 테스트 갱신
src/test/java/konkuk/thip/notification/adapter/in/web/NotificationMarkToCheckedApiTest.java
NOTIFICATION_ALREADY_CHECKED 경로 제거. 이미 읽은 경우 200 OK와 리다이렉트 데이터(data.route=FEED_USER, data.params.userId=123) 검증 추가. Forbidden(403) 시나리오 유지.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor U as User
  participant C as NotificationCommandController
  participant S as NotificationMarkService
  participant P as NotificationCommandPort
  participant N as Notification (Domain)

  U->>C: POST /notifications/{id}/read
  C->>S: markToChecked(userId, notificationId)
  S->>N: markToChecked()
  alt 아직 미읽음
    N-->>S: 상태 변경 성공
    S->>P: update(notification)
    P-->>S: ok
    S-->>C: RedirectSpec 반환
    C-->>U: 200 OK + redirect data
  else 이미 읽음
    N-->>S: InvalidStateException
    S-->>C: (예외 무시) RedirectSpec 반환
    C-->>U: 200 OK + redirect data
  end
  opt 권한 없음
    S-->>C: AccessForbidden
    C-->>U: 403 Forbidden
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

👻 성준, 🔥 hotfix

Poem

토끼는 알림을 톡톡, 귀 쫑긋 하며 본다
이미 읽은 발자국, 다시 혼내진 않는다
살짝 점프해 리다이렉트 길을 건네고
200 OK, 당근처럼 달콤한 코드
핫픽스로 뚝딱, 오늘도 평화다 🥕✨

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed 제목 "[hotfix] 알림 읽음 처리 api 수정"은 변경의 핵심(알림 읽음 처리 API의 동작 수정)을 간결하게 요약하고 있어 PR을 훑는 동료가 주요 변경을 빠르게 이해할 수 있습니다.
Linked Issues Check ✅ Passed 연결된 이슈 #312의 요구사항인 "이미 읽음 처리된 알림에 대해 400 대신 리다이렉트에 필요한 데이터를 응답"하도록 변경하는 목표가 충족되었습니다; NotificationMarkService에서 InvalidStateException을 무시하도록 처리하고 Swagger 설명과 API 테스트를 해당 동작으로 업데이트한 점이 이를 뒷받침합니다.
Out of Scope Changes Check ✅ Passed 변경은 알림 읽음 처리 관련 서비스 로직, 컨트롤러 설명, Swagger 응답 명세 및 관련 테스트에 국한되어 있으며 원래 이슈의 목적과 무관한 파일이나 기능의 수정은 보이지 않습니다.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch hotfix/#312-notification-check-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 and usage tips.

@github-actions
Copy link
Copy Markdown

Test Results

479 tests   479 ✅  41s ⏱️
142 suites    0 💤
142 files      0 ❌

Results for commit 6cb40fe.

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/main/java/konkuk/thip/notification/application/service/NotificationMarkService.java (1)

33-37: 긴급: Notification.getRedirectSpec() 널-체크 필요 (NPE 위험, NotificationMarkService.java:33-37)

notification.getRedirectSpec().route()가 redirectSpec == null일 때 NPE가 발생합니다. 레포에서 redirectSpec이 누락되거나 null로 생성되는 지점이 확인되었습니다:

  • src/main/java/konkuk/thip/message/application/service/RoomNotificationDispatchService.java — Notification.builder()...build() (97-100)
  • src/main/java/konkuk/thip/message/application/service/FeedNotificationDispatchService.java — Notification.builder()...build() (88)
  • src/test/java/konkuk/thip/notification/domain/NotificationTest.java — .redirectSpec(null) 사용 (50)
  • src/main/java/konkuk/thip/common/util/TestEntityFactory.java — createNotification(...)에서 redirectSpec 미설정 빌드 (376-384)

조치(택1): 빌더/데이터로 redirectSpec 존재 보장 또는 널-세이프 처리 적용. 간단한 널-세이프 예시:

-        return new NotificationMarkToCheckedResponse(
-                notification.getRedirectSpec().route(),
-                notification.getRedirectSpec().params()
-        );
+        var spec = notification.getRedirectSpec();
+        if (spec == null) {
+            // TODO: 합의된 기본값으로 변경하거나 data=null 정책 적용
+            return new NotificationMarkToCheckedResponse(null, Map.of());
+        }
+        return new NotificationMarkToCheckedResponse(spec.route(), spec.params());
🧹 Nitpick comments (4)
src/main/java/konkuk/thip/common/swagger/SwaggerResponseDescription.java (1)

358-358: 오타 수정 제안: 'Notiification' → 'Notification'

사용자 문서에 노출되는 주석/섹션명은 철자를 맞추는 것이 좋습니다.

-    // Notiification
+    // Notification
src/main/java/konkuk/thip/notification/application/service/NotificationMarkService.java (1)

26-31: 예외 삼킴 범위를 축소하세요 — 이미 읽음만 무시, 나머지는 전파

InvalidStateException을 전부 무시하면 다른 유효하지 않은 상태도 조용히 통과할 수 있습니다. “이미 읽음” 케이스만 선별해 무시하고, 그 외 상태는 재던지도록 좁혀주세요.

가능한 접근:

  • 도메인에 isChecked()가 있으면 사전 가드로 예외 자체를 피합니다.
  • “이미 읽음”에 한정된 전용 예외(예: AlreadyCheckedException)로 분리하거나, 예외 내 구분자(에러코드 등)로 필터링 후 나머지는 rethrow.

예시(구분자 필터링이 가능한 경우):

         try {
             notification.markToChecked();
             notificationCommandPort.update(notification);
-        } catch (InvalidStateException e) {
-            // 이미 알림 읽음 처리된 경우 -> 무시
-        }
+        } catch (InvalidStateException e) {
+            // 이미 읽음 상태만 무시, 그 외는 전파
+            if (!e.getMessage().contains("ALREADY_CHECKED")) { // 예: 구분자 사용 (실제 구현에 맞게 교체)
+                throw e;
+            }
+        }

또는 (사전 가드가 가능한 경우):

-        try {
-            notification.markToChecked();
-            notificationCommandPort.update(notification);
-        } catch (InvalidStateException e) {
-            // 이미 알림 읽음 처리된 경우 -> 무시
-        }
+        if (!notification.isChecked()) {
+            notification.markToChecked();
+            notificationCommandPort.update(notification);
+        }
src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java (1)

70-72: 설명 보강 제안: 응답 코드/특성 명시

이미 읽음인 경우에도 200(OK)과 동일 스키마로 응답하는 “멱등(idempotent)” 동작임을 설명에 명시하면, 클라이언트 구현과 문서가 더 명확해집니다.

예: “이미 읽음인 경우에도 200 OK와 동일한 redirect 데이터 스키마를 반환합니다(멱등).”

src/test/java/konkuk/thip/notification/adapter/in/web/NotificationMarkToCheckedApiTest.java (1)

115-115: 주석 업데이트 필요: “→ 400” → “→ 200”

설명 주석이 과거 기대값(400)으로 남아있습니다. 현재 기대값(200)에 맞게 수정하세요.

-        // when & then: 다시 읽음 처리 시도 → 400
+        // when & then: 다시 읽음 처리 시도 → 200(OK)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 50c7cee and 6cb40fe.

📒 Files selected for processing (4)
  • src/main/java/konkuk/thip/common/swagger/SwaggerResponseDescription.java (1 hunks)
  • src/main/java/konkuk/thip/notification/adapter/in/web/NotificationCommandController.java (1 hunks)
  • src/main/java/konkuk/thip/notification/application/service/NotificationMarkService.java (2 hunks)
  • src/test/java/konkuk/thip/notification/adapter/in/web/NotificationMarkToCheckedApiTest.java (2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#113
File: src/main/java/konkuk/thip/recentSearch/adapter/out/persistence/RecentSearchCommandPersistenceAdapter.java:38-44
Timestamp: 2025-07-30T14:05:04.945Z
Learning: seongjunnoh는 코드 최적화 제안에 대해 구체적인 기술적 근거와 효율성 차이를 이해하고 싶어하며, 성능 개선 방식에 대한 상세한 설명을 선호한다.
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#93
File: src/main/java/konkuk/thip/room/adapter/out/persistence/RoomQueryPersistenceAdapter.java:49-114
Timestamp: 2025-07-28T16:44:31.224Z
Learning: seongjunnoh는 코드 중복 문제에 대한 리팩토링 제안을 적극적으로 수용하고 함수형 인터페이스를 활용한 해결책을 선호한다.
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#285
File: src/main/java/konkuk/thip/room/adapter/out/jpa/RoomStatus.java:1-7
Timestamp: 2025-08-31T05:25:14.845Z
Learning: seongjunnoh는 enum 의존성에 대해 유연한 접근을 선호하며, 도메인→어댑터 레이어 참조와 같은 아키텍처 layering 원칙보다 실용적인 구현을 우선시한다.
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#195
File: src/main/java/konkuk/thip/feed/application/mapper/FeedQueryMapper.java:0-0
Timestamp: 2025-08-13T05:22:32.287Z
Learning: seongjunnoh는 데이터 무결성과 중복 방지에 대한 고민이 깊으며, LinkedHashSet을 활용한 중복 제거와 순서 보장을 동시에 달성하는 솔루션을 선호한다.
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#305
File: src/main/java/konkuk/thip/notification/adapter/out/persistence/repository/NotificationQueryRepository.java:9-13
Timestamp: 2025-09-17T06:40:49.863Z
Learning: seongjunnoh는 메서드 네이밍 시 구현 세부사항보다 비즈니스 의도를 반영하는 것을 선호하며, 미래 확장성과 아키텍처 변화를 고려한 설계 철학을 가지고 있다.
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#278
File: src/main/java/konkuk/thip/TestTokenController.java:0-0
Timestamp: 2025-08-24T09:33:52.982Z
Learning: seongjunnoh는 Spring의 ConditionalOnProperty 동작 원리를 정확히 이해하고 있으며, 보안 이슈에 대해서도 실질적인 위험성을 기준으로 판단하는 실용적 접근을 선호한다.
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#278
File: src/main/java/konkuk/thip/common/exception/code/ErrorCode.java:210-211
Timestamp: 2025-08-24T09:40:48.595Z
Learning: seongjunnoh는 HTTP 상태 코드 선택에 대해 기술적 근거와 코드베이스 내 일관성을 중요하게 생각하며, 구체적인 사례 분석을 통한 설명을 선호한다.
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#180
File: src/main/java/konkuk/thip/room/application/service/AttendanceCheckCreateService.java:22-40
Timestamp: 2025-08-14T09:15:31.371Z
Learning: seongjunnoh는 기술적 완벽성보다 실제 비즈니스 시나리오와 사용자 행동 패턴을 우선 고려하며, 발생 가능성이 낮은 엣지 케이스보다는 실용적인 구현을 선호한다.
Learnt from: seongjunnoh
PR: THIP-TextHip/THIP-Server#112
File: src/main/java/konkuk/thip/feed/adapter/out/persistence/repository/FeedQueryRepositoryImpl.java:272-272
Timestamp: 2025-07-30T10:44:34.115Z
Learning: seongjunnoh는 피드 커서 페이지네이션에서 LocalDateTime 단일 커서 방식을 선호하며, 복합 키 기반 커서보다 구현 단순성과 성능을 우선시한다.
🧬 Code graph analysis (1)
src/test/java/konkuk/thip/notification/adapter/in/web/NotificationMarkToCheckedApiTest.java (1)
src/test/java/konkuk/thip/common/util/TestEntityFactory.java (1)
  • TestEntityFactory (35-403)
⏰ 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). (1)
  • GitHub Check: build
🔇 Additional comments (4)
src/test/java/konkuk/thip/notification/adapter/in/web/NotificationMarkToCheckedApiTest.java (4)

95-96: 테스트 시나리오 갱신 적절

이미 읽음 케이스를 성공(200) 경로로 전환한 테스트 설명과 흐름이 변경 의도와 일치합니다.


100-103: redirectSpec 준비 좋습니다

리다이렉트 목적지를 명시적으로 부여해 응답 구조를 검증하는 방식이 명확합니다.


105-105: 엔티티 생성 시 redirectSpec 포함 OK

프로덕션 경로와 동일 전제(redirectSpec 존재)를 테스트에 반영해 회귀 위험을 줄였습니다.


121-123: 응답 검증 포인트 적절

route와 params.userId를 검증해 계약을 충분히 커버합니다.

Comment on lines 381 to 383
NOTIFICATION_NOT_FOUND,
NOTIFICATION_ACCESS_FORBIDDEN,
NOTIFICATION_ALREADY_CHECKED
NOTIFICATION_ACCESS_FORBIDDEN
))),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue

🧩 Analysis chain

스펙 정합성 OK — 이미 읽음 에러 제거가 의도와 일치합니다

NOTIFICATION_MARK_TO_CHECKED에서 NOTIFICATION_ALREADY_CHECKED 제거는 서비스/컨트롤러/테스트 변경과 일관됩니다.

레거시 참조가 남아있지 않은지 확인 부탁드립니다. 아래 스크립트로 잔존 참조를 점검할 수 있습니다.


🏁 Script executed:

#!/bin/bash
# NOTIFICATION_ALREADY_CHECKED 사용 흔적 검사
rg -nC2 'NOTIFICATION_ALREADY_CHECKED'

Length of output: 2752


레거시 참조 제거 필요 — NOTIFICATION_ALREADY_CHECKED 참조가 남아있음

Swagger 변경(이미 읽음 에러 제거)의 의도대로라면 아래 참조들을 제거하거나 스펙에 맞게 수정하세요.

  • src/main/java/konkuk/thip/common/exception/code/ErrorCode.java:238 — NOTIFICATION_ALREADY_CHECKED 정의
  • src/main/java/konkuk/thip/notification/domain/Notification.java:11(import), 51(throw) — 사용 위치
  • src/test/java/konkuk/thip/notification/domain/NotificationTest.java:9(import), 40(assertion) — 테스트에서 사용

해당 참조들을 삭제하거나 테스트·도메인 로직을 스펙(이미 읽음 에러 제거)에 맞게 업데이트하세요.

🤖 Prompt for AI Agents
In src/main/java/konkuk/thip/common/swagger/SwaggerResponseDescription.java
around lines 381-383, the code still references a legacy error
NOTIFICATION_ALREADY_CHECKED which should be removed per the recent spec change;
remove that enum constant usage here and then delete or refactor all remaining
references: remove NOTIFICATION_ALREADY_CHECKED from
src/main/java/konkuk/thip/common/exception/code/ErrorCode.java (line ~238),
remove the import and any throw statements in
src/main/java/konkuk/thip/notification/domain/Notification.java (remove the
import at line 11 and the throw at line 51 or replace with the new behavior),
and update src/test/java/konkuk/thip/notification/domain/NotificationTest.java
by removing the import at line 9 and adjusting the assertion at line 40 to
reflect the new spec (either assert success/no-error or the new error type);
ensure compilation and tests pass after these deletions/adjustments.

@seongjunnoh seongjunnoh merged commit 0913cfb into develop Sep 24, 2025
4 checks passed
@seongjunnoh seongjunnoh deleted the hotfix/#312-notification-check-api branch September 24, 2025 09:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[THIP2025-358] [hotfix] 알림 읽음 처리 api 수정

1 participant