Skip to content

[Feat/#109] 회원 알림 설정 조회·수정 API 추가 - #110

Open
tnals0924 wants to merge 4 commits into
mainfrom
feat/#109-notification-settings
Open

tnals0924 wants to merge 4 commits into
mainfrom
feat/#109-notification-settings

Conversation

@tnals0924

Copy link
Copy Markdown
Member

#️⃣연관된 이슈

🎯 해결하려는 문제가 무엇인가요?

학생 앱 알림 설정 화면에서 카테고리별 푸시 수신 여부를 조회·수정하는 API를 추가합니다.

// GET /v1/app/notifications/settings 응답 data
// PUT /v1/app/notifications/settings 요청 바디도 같은 형태 (네 값 모두 필수)
{ "rentalEnabled": true, "eventEnabled": false, "lockerEnabled": false, "noticeEnabled": false }
화면 필드
빌릴게 알림 rentalEnabled
행사 알림 eventEnabled
게시판 알림 (새 공지·열린피드백 답변) noticeEnabled
사물함 알림 lockerEnabled

전체 알림은 저장하지 않습니다. 앱이 네 값이 모두 true면 켜진 것으로 보여주고, 전체 알림을 누르면 네 값을 한꺼번에 true나 false로 보내면 됩니다.

❓ 왜 해결해야 하나요?

FCM을 notification 페이로드로 보내므로 앱이 백그라운드나 종료 상태일 때는 OS가 알림을 바로 띄웁니다. Android는 onMessageReceived가 불리지 않고, iOS는 알림을 숨기려면 Apple 승인이 필요한 entitlement가 있어야 합니다. 앱에서 받은 알림을 걸러낼 수 없으니 설정을 서버에 두고 발송할 때 걸러야 합니다.

V1에 member_notification_settings 테이블과 도메인·엔티티는 있었지만, 값을 읽고 쓰는 경로가 없었습니다.

⭐ 어떻게 해결했나요?

  • 조회·수정: MemberNotificationSettingService(notification 도메인)를 새로 만들고 컨트롤러가 바로 부릅니다.
    • 수정은 네 값을 모두 받아 덮어씁니다(PUT). 전체 알림 토글이 네 값을 한 번에 바꾸는 동작과 맞습니다.
    • MemberNotificationSetting.update가 바뀌었는지 돌려주고, 바뀐 값이 없으면 저장하지 않습니다(Member.updateFcmToken과 같은 방식).
  • 가입할 때 생성: 회원가입이 MemberSignUpUseCase를 거치도록 바꿨습니다. MemberService.signUp과 기본 설정 생성(모두 켜짐)을 한 트랜잭션으로 묶습니다.
    • member와 notification은 다른 도메인이라 서비스끼리 직접 부르지 않고 UseCase에서 조합했습니다(RentalApplyUseCase와 같은 구조).
    • 필수 약관이 늘어 다시 가입하는 회원은 이미 설정이 있으므로 건너뜁니다(createDefaultIfAbsent). 그 회원이 바꿔 둔 값은 그대로 남습니다.
  • 기존 회원: V17__insert_default_member_notification_settings.sql이 설정이 없는 활성 회원 전원에게 기본 설정을 만듭니다. 아직 가입을 마치지 않은 회원도 포함되고, 나중에 가입하면 이미 있는 설정을 그대로 씁니다.
  • 새 에러 코드: NotificationErrorCode.NOTIFICATION_SETTING_NOT_FOUND(404)

🧩 이 PR의 한계 & 트레이드오프

  • 발송 필터는 아직 없음: 지금은 PushNotificationClient를 호출해 푸시를 보내는 코드가 없습니다. 이번 PR은 설정 저장까지만 다룹니다. 발송을 구현할 때 꺼진 카테고리는 푸시만 보내지 않고 알림함(notifications)에는 저장하기로 정했습니다(Swagger 설명에도 적어 둠).
  • 로컬 검증 범위: 로컬에 DB가 없어 컴파일과 ModularityTests·DomainImplAccessTests까지만 확인했습니다. V17 마이그레이션과 API 호출은 dev에서 확인이 필요합니다.

⛓️ 기존 기능에 미치는 영향

  • 회원가입(POST /v1/app/members/sign-up)이 성공하면 member_notification_settings에 row가 하나 생깁니다. 요청·응답 형식은 바뀌지 않습니다.
  • 회원가입 Swagger 설명에 "가입하면 알림 설정이 모두 켜진 상태로 만들어진다"를 추가했습니다.
  • 새 Swagger 태그 알림이 생깁니다.

🔀 Edge Case & 실패 시나리오

상황 응답
수정 요청에서 값 하나라도 누락 400 INVALID_INPUT
설정 row 없음 (V17 이후 가입 없이 생긴 회원 등) 404 NOTIFICATION_SETTING_NOT_FOUND
지금 값과 같은 값으로 수정 200 (저장 생략)
가입 중 설정 생성 실패 회원가입 전체 롤백
  • V17 이후 가입 전 회원: 로그인만 하고 가입을 마치지 않은 회원은 설정이 없어 조회하면 404입니다. 앱은 가입 화면을 먼저 띄우므로 이 화면에 오지 않습니다.
  • 같은 회원의 가입 요청이 동시에 두 번: 둘 다 설정이 없다고 보고 만들면 유니크 키(uk_member_notification_settings_member_id) 위반으로 한쪽이 500입니다. 같은 경합에서 약관 동의 저장도 이미 유니크 키로 실패하므로 따로 처리하지 않았습니다.

📋 검토한 대안과 선택 이유

  • 앱에서 받은 알림 걸러내기: 위 이유로 포그라운드에서만 동작해서 제외했습니다. data-only 메시지로 바꾸면 가능하지만, iOS 전달 제한과 강제 종료 시 미수신 문제로 이미 쓰지 않기로 했습니다.
  • all_enabled 컬럼 추가: 화면에서 전체 알림이 꺼져 있어도 개별 알림이 켜져 있을 수 있어 독립 스위치가 아니라 파생값으로 봤습니다. 저장하면 네 값과 어긋날 수 있어 두지 않았습니다.
  • row가 없으면 기본값으로 취급(지연 생성): 마이그레이션이 필요 없지만, 발송할 때도 "없음 = 모두 켜짐"을 매번 처리해야 해서 가입 시 생성으로 정했습니다.
  • /v1/app/members/me/notification-settings: FCM 토큰 API(/members/me/fcm-token)와 경로는 맞지만, notification 도메인을 별도 컨트롤러로 두고 나중에 알림함 목록도 /v1/app/notifications에 둘 수 있게 /v1/app/notifications/settings로 정했습니다.

💬 리뷰 포인트

  • MemberSignUpUseCase: 가입과 설정 생성을 한 트랜잭션으로 묶은 것, 재가입 시 기존 설정을 유지하는 것
  • V17: 가입 전 회원까지 포함해서 만드는 범위
  • API 경로 /v1/app/notifications/settings

@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 59 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: billilge/stream-server/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2e519cd8-f6fc-4eb6-9d14-042aa427e8c3
📥 Commits

Reviewing files that changed from the base of the PR and between bccbe97 and 68b1a8b.

📒 Files selected for processing: 16
  • api/app-api/src/main/java/kr/ac/kookmin/stream/api/app/core/member/AppMemberApi.java
  • api/app-api/src/main/java/kr/ac/kookmin/stream/api/app/core/member/AppMemberController.java
  • api/app-api/src/main/java/kr/ac/kookmin/stream/api/app/core/member/usecase/MemberSignUpUseCase.java
  • api/app-api/src/main/java/kr/ac/kookmin/stream/api/app/core/notification/AppNotificationApi.java
  • api/app-api/src/main/java/kr/ac/kookmin/stream/api/app/core/notification/AppNotificationController.java
  • api/app-api/src/main/java/kr/ac/kookmin/stream/api/app/core/notification/request/MemberNotificationSettingUpdateRequest.java
  • api/app-api/src/main/java/kr/ac/kookmin/stream/api/app/core/notification/response/MemberNotificationSettingResponse.java
  • core/domain/member/src/main/java/kr/ac/kookmin/stream/member/domain/notification/domain/MemberNotificationSetting.java
  • core/domain/member/src/main/java/kr/ac/kookmin/stream/member/domain/notification/domain/MemberNotificationSettingUpdateCommand.java
  • core/domain/member/src/main/java/kr/ac/kookmin/stream/member/domain/notification/domain/NotificationErrorCode.java
  • core/domain/member/src/main/java/kr/ac/kookmin/stream/member/domain/notification/repository/MemberNotificationSettingRepository.java
  • core/domain/member/src/main/java/kr/ac/kookmin/stream/member/domain/notification/service/MemberNotificationSettingService.java
  • core/domain/member/src/main/java/kr/ac/kookmin/stream/member/domain/notification/service/impl/MemberNotificationSettingServiceImpl.java
  • infrastructure/db/src/main/java/kr/ac/kookmin/stream/db/member/MemberNotificationSettingJpaRepository.java
  • infrastructure/db/src/main/java/kr/ac/kookmin/stream/db/member/MemberNotificationSettingRepositoryImpl.java
  • infrastructure/db/src/main/resources/db/migration/V17__insert_default_member_notification_settings.sql
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

public void createDefaultIfAbsent(Long memberId) {
if (memberNotificationSettingRepository.existsByMemberId(memberId)) {
return;
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

재가입 하는 회원의 기존 알림 설정을 유지하기 위한 덮어쓰지 않고 그냥 두는 점 이해했습니다!

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.

회원 알림 설정 조회·수정 API 추가

2 participants