Skip to content

MSG-432 feat: 알림에 이동 대상을 저장해 푸시와 알림함으로 딥링크 재료를 내려준다 - #287

Merged
Ss0Mae merged 9 commits into
developfrom
feature/MSG-432-notification-deeplink-prd
Sep 24, 2026
Merged

Ss0Mae merged 9 commits into
developfrom
feature/MSG-432-notification-deeplink-prd

Conversation

@Ss0Mae

@Ss0Mae Ss0Mae commented Sep 23, 2026 •

Copy link
Copy Markdown
Member

🎫 관련 티켓

  • Closes MSG-432 — 서버 몫. 앱 몫(푸시 탭·알림함 행 탭 라우팅)은 FE 레포 후속

작업 내용

  • PRD docs/prd/MSG-432-prd.md 미해결 질문 4건을 확정하고 검토됨으로 올렸다 (2026-09-24 성민): FRIEND → 지도 홈(서버는 USER 기록), REMIND → 홈 유지, MODERATION → 영상 화면(재생 API가 소유자에게 BLINDED를 통과시킴), GRID → 격자 이동·하이라이트까지(셀 시트 안 열음)
  • 스펙 docs/spec/MSG-432.md 신규 (D-1D-6, AC-432-0107, 작업 로그)
  • V56 notifications.target_type VARCHAR(20)·target_id VARCHAR(64) NULL 허용 + CHECK 2개(짝 일치 chk_notifications_target_pair, 5종 chk_notifications_target_type)
  • NotificationTargetType(VIDEO·GRID·BADGE·EVENT_OCCURRENCE·USER) enum, NotificationTarget record(팩토리 5개, null 거부), Notification.target() 조립 접근자
  • NotificationCommandService.record 6인자 오버로드(5인자는 null 위임). recordEventStart는 시그니처 그대로 두고 INSERT…SELECT 상수 열로 EVENT_OCCURRENCE + 회차 id
  • NotificationSender.send(…, category, target) → FcmNotificationSender.dataOf: FCM data에 category 항상, 대상 있을 때만 targetType·targetId. notification 표시 필드·웹푸시 설정 무변경(혼합 페이로드 유지)
  • NotificationItemResponseDto +targetType·targetId(nullable, required 목록 포함)
  • 발생 지점 7곳 배선: VIDEO 완료·실패/MODERATION 가림·해제 → 영상, HOTZONE → 격자, BADGE 획득·임박 → 뱃지, FRIEND 요청 → 요청자·수락 → 수락자, EVENT 일정 변경 → 회차. REMIND·WEEKLY는 대상 없음으로 무변경
  • 테스트: 신규 8건 + 기존 발생 지점 통합 테스트 7곳에 대상 컬럼 단언 확장. 마커 // 검증: FR-NOTI-12, AC-432-NN, RTM 재생성으로 AC 7개 전부 연결
  • SRS FR-NOTI-12 근거 갱신(진행 중 유지 — 앱 몫 남음), srs-changelog 행, status.md notification 섹션 한 줄

🤔 고민한 내용

  • 대상을 event_key 파싱이 아니라 별도 컬럼으로: event_key는 dedupe용 내부 키라 형식이 카테고리마다 다르고 응답 비노출이 계약(MSG-434)이다. 두 컬럼을 같은 INSERT 문장에 넣어 "대상 저장 실패가 알림 기록을 막는" 별도 경로가 없다.
  • CHECK를 DB에 둔 이유: 값 객체가 짝 어긋남을 코드에서 막지만 native INSERT 문장이 둘(insert·insertEventStart)이라 DB가 최종 방어선. 카테고리 CHECK와 같은 방식이고 새 종류는 SRS 개정 + 마이그레이션이 같이 간다.
  • recordEventStart 시그니처 무변경: 이미 회차 id를 받으므로 SQL 상수 열로 처리해 호출자·테스트를 건드리지 않았다.
  • 대상 없을 때 data 키 자체를 생략: 빈 문자열·"null"을 넣으면 앱 판정에 해석 여지가 생긴다. 기존 앱 버전은 모르는 키를 무시하므로 하위 호환.
  • MulticastMessage는 읽기 접근자가 없어 data 조립을 dataOf(...) 정적 메서드로 떼어 단위 검증했다.
  • required 목록에 nullable 필드 포함: 이 레포의 required는 키 존재를 뜻한다(MSG-319 가드가 전체 빌드에서 잡아 수정).
  • 핵심 SQL:
    INSERT INTO notifications (user_id, category, event_key, title, body, created_at, target_type, target_id)
    VALUES (:userId, :category, :eventKey, :title, :body, statement_timestamp() AT TIME ZONE 'UTC', :targetType, :targetId)
    ON CONFLICT (user_id, event_key) DO NOTHING

👀 리뷰 포인트

  • NotificationSender.send 시그니처 변경이 인터페이스 구현체(FCM 1개)와 컨슈머 호출부·테스트 스텁 11곳을 함께 바꿨다. 놓친 호출부가 없는지(컴파일이 잡지만 목 스텁의 any(), any() 확장은 눈으로 확인 부탁)
  • target_id VARCHAR(64)가 격자 id·숫자 id 모두에 충분한지(현재 격자 id 최대 길이 기준 여유 있음)
  • 웹 푸시 클릭 라우팅과 MISSION_NEARBY 로컬 알림은 이 계약 밖(PRD 비목표)

검증: 전체 빌드 통과(테스트 3,196건, 스킵 6), 변경 영향 클래스 11개 236건 통과. Codex 교차 리뷰 스펙 1R·코드 1R 결함 없음.

🤖 Generated with Claude Code

- docs/prd/MSG-432-prd.md: 이동 대상(targetType+targetId) 저장·푸시 data·알림함 응답 계약, 카테고리별 대상 규칙,
  앱 목적지 표, 변경 파일 목록(서버·앱), 미해결 질문 4건(FRIEND 목적지·REMIND 목적지·MODERATION 영상 접근·GRID 진입 깊이)
- docs/srs.md FR-NOTI-12 계획 → 진행 중, docs/rtm.md 동기화

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@claude

claude Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Claude finished @Ss0Mae's task in 3m 39s —— View job


리뷰 완료

  • PR 컨텍스트·변경 파일 확인
  • SRS/RTM 정합성 확인
  • PRD 본문 검토
  • 발견 사항 인라인 코멘트로 남기기
  • 추적 코멘트 정리

확인 범위: docs/prd/MSG-432-prd.md(신규 155줄), docs/rtm.md(+2/-2), docs/srs.md(+1/-1). 구현 코드 변경은 없는 PRD 게이트 문서라 우선순위 2·3(스펙 대비 구현, 실행 결함)은 해당 사항이 없습니다. PRD 본문이 인용한 기존 코드 근거(FcmNotificationSender.buildMessage()의 data 필드, 7개 알림 발생 지점의 event_key 포맷과 대상 ID 가용성, NotificationPageResponseDto/NotificationItemResponseDto 실제 구조, MSG-434 PRD의 이월 문구, V56 마이그레이션 번호가 origin/develop 기준 실제로 빈 다음 번호인지)은 코드와 대조해 전부 일치를 확인했습니다.

발견

라벨 위치 요약
P1 docs/rtm.md:242 (342행도 동일 원인) docs/srs.md의 FR-NOTI-12 상태를 계획→진행 중으로 바꾸면서 docs/rtm.md를 손으로 맞춰 고쳤는데, scripts/generate-rtm.sh를 실제로 돌리면 테스트 미연결 + 비-계획/폐기 상태 조합이라 "검증 공백(조치 대상)" 절로 분류되어 커밋된 내용과 달라집니다. CI RTM 신선도 검사 스텝이 diff로 이를 잡아 실패합니다. bash scripts/generate-rtm.sh 재실행 후 재생성본 커밋 필요.

나머지는 미해결 질문 4건(§8)이 이미 문서 안에서 스스로 짚고 있는 설계 공백(FRIEND/REMIND 목적지, MODERATION 소유자 접근, GRID 진입 깊이)이라 별도로 지적하지 않았습니다. 병렬 브랜치 경합(마이그레이션 번호·developCode 대역·Owner 계약)은 이 PR이 실제 구현 파일을 건드리지 않아 해당 없음입니다.
· 브랜치: feature/MSG-432-notification-deeplink-prd


작업 근거

  • Applied rules: response-pattern(해당 없음 — API 변경 없음), CLAUDE.md 개발 파이프라인(PRD 게이트 단계 검증)
  • Applied skills: 없음
  • Why this routing: "이 PR을 리뷰해줘" + 커스텀 지침의 우선순위 규칙(병렬 경합→스펙 대비 구현→실행 결함→PR 본문 주장 검증)을 그대로 적용. 이 PR은 구현 코드가 없는 PRD 문서라 실제로 검증 가능했던 것은 PRD가 인용한 기존 코드 사실관계와, 문서 자체가 CI 재생성 스크립트와 어긋나는지였습니다.
  • 수정하지 않은 파일: 없음 (리뷰만 수행, 코드 수정 없음)

Comment thread docs/rtm.md Outdated
Ss0Mae and others added 8 commits September 23, 2026 11:31
Q1 FRIEND는 홈(서버는 USER 기록), Q2 REMIND는 홈 유지, Q3 MODERATION은 VIDEO(재생 API가 소유자에게 BLINDED를 통과시킴), Q4 GRID는 이동·하이라이트까지. 2026-09-24 성민 확정.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
V56 target_type·target_id(NULL 허용, 짝·종류 CHECK). NotificationTarget 값 객체와 record 6인자 오버로드, 회차 시작 알림은 INSERT…SELECT 상수 열로 EVENT_OCCURRENCE 를 넣는다.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
FCM data 는 notificationId·category 에 대상이 있을 때만 targetType·targetId 를 더한다(빈 값 금지). notification 표시 필드와 웹푸시 설정은 그대로다.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
영상 완료·실패와 가림·해제는 영상, 핫구역은 격자, 뱃지 획득·임박은 뱃지, 친구 요청·수락은 상대 사용자, 일정 변경은 회차. 스트릭·주간 요약은 대상 없음으로 무변경.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
전체 빌드에서 ResponseSchemaNullabilityTest 가 잡았다. 이 레포의 required 는 값이 아니라 키 존재를 뜻해 nullable 필드도 목록에 든다 (MSG-319).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Ss0Mae Ss0Mae changed the title MSG-432 docs: 알림 딥링크 PRD 초안 (검토 요청) MSG-432 feat: 알림에 이동 대상을 저장해 푸시와 알림함으로 딥링크 재료를 내려준다 Sep 24, 2026
@github-actions

Copy link
Copy Markdown

테스트 커버리지

Overall Project 95.88% 🍏
Files changed 100% 🍏

File Coverage
BadgeAwardServiceImpl.java 100% 🍏
NotificationPageResponseDto.java 100% 🍏
Notification.java 100% 🍏
NotificationTarget.java 100% 🍏
NotificationTargetType.java 100% 🍏
NotificationCommandServiceImpl.java 100% 🍏
NotificationSender.java 100% 🍏
VideoStatusWriter.java 97.41% 🍏
HotZoneEntryDetector.java 97.01% 🍏
EventSeeder.java 95.42% 🍏
FriendServiceImpl.java 93.94% 🍏
NotificationConsumer.java 93.04% 🍏
VideoModerationServiceImpl.java 89.13% 🍏
FcmNotificationSender.java 87.36% 🍏

@Ss0Mae
Ss0Mae merged commit b15fd3a into develop Sep 24, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant