Skip to content

refactor: SYSTEM 메시지 페이로드 저장 계약 정리#138

Merged
parkjuyeong0312 merged 11 commits into
devfrom
refactor/mongo-message-payload
Jun 8, 2026
Merged

refactor: SYSTEM 메시지 페이로드 저장 계약 정리#138
parkjuyeong0312 merged 11 commits into
devfrom
refactor/mongo-message-payload

Conversation

@parkjuyeong0312

@parkjuyeong0312 parkjuyeong0312 commented Jun 8, 2026

Copy link
Copy Markdown
Member

변경 내용

  • SYSTEM 메시지 MongoDB 문서와 REST/STOMP 응답에서 content 키를 제외하도록 정리
  • SYSTEM metadata에서 닉네임/프로필 fallback 데이터를 제거하고 eventType/userId 식별자만 유지
  • messages topic과 members topic payload DTO의 Swagger/Springwolf 설명을 실제 계약에 맞게 갱신
  • features.md, erd.md, ADR, superpowers spec/plan에 SYSTEM 메시지 페이로드 정리 결정 반영
  • SYSTEM 메시지 BSON 저장, REST 응답, realtime 직렬화 회귀 테스트 보강

변경 이유

  • 시스템 메시지 표시 문구를 서버 저장 문자열이 아니라 클라이언트 멤버 맵 lookup으로 일관되게 조립하기 위함
  • 탈퇴/닉네임 변경 이후에도 오래된 닉네임 fallback이 MongoDB와 API payload에 남는 계약을 제거하기 위함

테스트

  • ./gradlew build
  • /review-code-against-docs 스킬로 검증
  • 그 외 수동 검증: Markdown conflict check, write-api-specs 기준 API/Realtime DTO 설명 정합성 확인

체크리스트

  • PR 제목이 커밋 컨벤션 형식을 따른다.
  • 변경 사유를 PR 설명에 기록했다.
  • 테스트 방법과 결과를 기록했다.
  • 문서 변경이 필요한 경우 반영했다.

하네스 변경 체크리스트

  • CLAUDE.md(AGENTS.md) 변경이 포함되어 있는가? 포함되지 않음
  • 변경 사유가 PR 설명에 기록되어 있는가?
  • 기존 규칙과 충돌하지 않는가?
  • 팀원에게 변경 사항을 공유했는가? PR로 공유

Summary by CodeRabbit

Release Notes

  • Refactor
    • 시스템 메시지 구조를 최적화하여 불필요한 사용자 정보 필드를 제거하고 메시지 페이로드를 간소화했습니다. 멤버십 이벤트(입장, 퇴장, 추방) 및 호스트 위임 메시지는 이제 식별자만 포함하도록 개선되었습니다.

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@parkjuyeong0312, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 45 minutes and 24 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9d92d0e3-a3db-48d9-ba47-4d06ae935618

📥 Commits

Reviewing files that changed from the base of the PR and between f792e8e and ba17312.

📒 Files selected for processing (2)
  • src/test/java/com/howaboutus/backend/messages/controller/MessageControllerTest.java
  • src/test/java/com/howaboutus/backend/messages/document/SystemMessagePayloadIntegrationTest.java
📝 Walkthrough

검토 개요

SYSTEM 메시지에서 display용 필드(content, nickname, profileImageUrl 등)를 제거하고, metadata에는 식별자만 포함하도록 저장 및 응답 구조를 정리합니다. 클라이언트가 metadata를 기반으로 방 멤버 정보를 조회하여 문구를 조립하는 구조로 변경됩니다.

변경 사항

SYSTEM 메시지 페이로드 정리

Layer / File(s) 요약
문서 및 설계 결정
docs/ai/decisions/*, docs/ai/erd.md, docs/ai/features.md, docs/superpowers/specs/*, docs/superpowers/plans/*
기존 ADR 상태를 "교체됨"으로 변경하고, SYSTEM 메시지에서 display 필드 제거 결정과 metadata 구조(eventType + userId), 클라이언트 조립 책임을 명시한 신규 ADR, 스펙, 계획 문서 추가. ERD와 기능 명세도 업데이트합니다.
서비스 계층 리팩토링
src/main/java/com/howaboutus/backend/messages/document/ChatMessage.java, src/main/java/com/howaboutus/backend/messages/service/SystemMessageService.java, src/main/java/com/howaboutus/backend/messages/service/MessageService.java, src/main/java/com/howaboutus/backend/messages/listener/*
ChatMessage.system() 메서드에서 content 파라미터 제거. SystemMessageServiceMessageService의 시스템 메시지 발행 메서드에서 nickname/profileImageUrl 인자 제거. 4개 리스너(MemberApproved, MemberKicked, MemberLeft, HostDelegated)의 호출 인자 축소.
API DTO 계약 변경
src/main/java/com/howaboutus/backend/realtime/service/dto/MessagePayload.java, src/main/java/com/howaboutus/backend/realtime/service/dto/RoomMemberPayload.java, src/main/java/com/howaboutus/backend/messages/controller/dto/MessageResponse.java
content 필드에 @JsonInclude(NON_NULL) 추가하여 null 값이 JSON 응답에서 제외됨. OpenAPI @Schema 설명을 갱신하여 SYSTEM 메시지에서 content 미포함, metadata 구조(eventType + userId), 클라이언트 조립 방식 명시.
테스트 검증
src/test/java/com/howaboutus/backend/messages/document/SystemMessagePayloadIntegrationTest.java, src/test/java/com/howaboutus/backend/messages/service/*Test.java, src/test/java/com/howaboutus/backend/messages/listener/*Test.java, src/test/java/com/howaboutus/backend/messages/controller/MessageControllerTest.java, src/test/java/com/howaboutus/backend/realtime/service/*BroadcasterTest.java, src/test/java/com/howaboutus/backend/ai/service/AiSummaryServiceTest.java
신규 통합 테스트: MongoDB BSON 저장 시 SYSTEM 메시지의 content 키 부재, metadata 키 집합(eventType, userId 등) 검증. 기존 단위 테스트: 시스템 메시지 호출 인자 축소, content null 기대값 갱신. API 테스트: 응답에서 content 필드 제외 검증. 브로드캐스터 테스트: JSON 직렬화에서 null content 제외 검증.

시퀀스 다이어그램

sequenceDiagram
    participant Event as 멤버 이벤트
    participant Listener as 리스너
    participant MessageService as MessageService
    participant SystemMessageService as SystemMessageService
    participant ChatMessage as ChatMessage
    participant Repository as MongoDB
    participant Response as API응답
    
    Event->>Listener: 이벤트발행(roomId, userId)
    Listener->>MessageService: sendMember*SystemMessage(roomId, userId)
    MessageService->>SystemMessageService: sendMember*SystemMessage(roomId, userId)
    SystemMessageService->>SystemMessageService: 메타데이터구성<br/>{eventType, userId}
    SystemMessageService->>ChatMessage: system(roomId, metadata)<br/>content=null
    ChatMessage->>Repository: 저장(content없음)
    
    Response->>Response: `@JsonInclude`(NON_NULL)<br/>content제외
    Response-->>Client: {messageType,metadata}<br/>(content미포함)
    Client->>Client: metadata.eventType+userId<br/>로방멤버조회
    Client-->>Client: 문구조립<br/>(닉네임/프로필포함)
Loading

검증 노력

🎯 3 (Moderate) | ⏱️ ~25 분

제안 레이블

backend, test

공개

🐰 시스템 메시지가 한결 가벼워졌네요,
표시는 클라이언트 손으로 돌려주고,
저장소에는 식별자만 남겨두니
데이터 신선함과 크기까지 챙겼습니다!
백과 프론트가 역할을 나누며
더욱 튼튼한 구조로 함께 그려갑니다. ✨

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목은 SYSTEM 메시지 페이로드 저장 계약 정리라는 핵심 변경사항을 명확하게 요약하고 있으며, 커밋 컨벤션 형식을 따릅니다.
Description check ✅ Passed PR 설명이 변경 내용, 변경 이유, 테스트 방법, 체크리스트를 모두 포함하고 있으며 제공된 템플릿 구조를 따릅니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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.

@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/test/java/com/howaboutus/backend/messages/controller/MessageControllerTest.java`:
- Line 130: In MessageControllerTest replace the non-deterministic Instant.now()
usage with a fixed instant to avoid flaky tests and Sonar warnings; either
substitute Instant.now() with a constant Instant.parse("YYYY-MM-DDTHH:MM:SSZ")
(e.g. Instant.parse("2020-01-01T00:00:00Z")) in the test, or introduce a fixed
Clock via Clock.fixed(...) and inject/provide it to the code under test
(referencing MessageControllerTest and the test method using Instant.now()) so
all time-dependent assertions use the deterministic fixed time.

In
`@src/test/java/com/howaboutus/backend/messages/document/SystemMessagePayloadIntegrationTest.java`:
- Around line 67-70: The tests in SystemMessagePayloadIntegrationTest currently
only assert presence of keys for MEMBER_LEFT and MEMBER_KICKED but do not verify
the actual metadata.userId value; update the assertions in the test methods
where Document metadata = raw.get("metadata", Document.class) (the MEMBER_LEFT
block around the existing
assertThat(metadata.getString("eventType")).isEqualTo("MEMBER_LEFT") and the
analogous MEMBER_KICKED block) to also assert that metadata.getString("userId")
equals the expected user id for each case so the tests fail on incorrect userId
regressions.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 33e3aa28-df38-4efc-9297-61dfa187d0d5

📥 Commits

Reviewing files that changed from the base of the PR and between beef4a2 and f792e8e.

📒 Files selected for processing (27)
  • docs/ai/decisions/20260607-1636-system-message-metadata-rendering.md
  • docs/ai/decisions/20260608-1553-system-message-payload-cleanup.md
  • docs/ai/erd.md
  • docs/ai/features.md
  • docs/superpowers/plans/2026-06-08-mongo-message-payload.md
  • docs/superpowers/specs/2026-06-08-mongo-message-payload-design.md
  • src/main/java/com/howaboutus/backend/messages/controller/dto/MessageResponse.java
  • src/main/java/com/howaboutus/backend/messages/document/ChatMessage.java
  • src/main/java/com/howaboutus/backend/messages/listener/HostDelegatedMessageListener.java
  • src/main/java/com/howaboutus/backend/messages/listener/MemberApprovedMessageListener.java
  • src/main/java/com/howaboutus/backend/messages/listener/MemberKickedMessageListener.java
  • src/main/java/com/howaboutus/backend/messages/listener/MemberLeftMessageListener.java
  • src/main/java/com/howaboutus/backend/messages/service/MessageService.java
  • src/main/java/com/howaboutus/backend/messages/service/SystemMessageService.java
  • src/main/java/com/howaboutus/backend/realtime/service/dto/MessagePayload.java
  • src/main/java/com/howaboutus/backend/realtime/service/dto/RoomMemberPayload.java
  • src/test/java/com/howaboutus/backend/ai/service/AiSummaryServiceTest.java
  • src/test/java/com/howaboutus/backend/messages/controller/MessageControllerTest.java
  • src/test/java/com/howaboutus/backend/messages/document/SystemMessagePayloadIntegrationTest.java
  • src/test/java/com/howaboutus/backend/messages/listener/HostDelegatedMessageListenerTest.java
  • src/test/java/com/howaboutus/backend/messages/listener/MemberApprovedMessageListenerTest.java
  • src/test/java/com/howaboutus/backend/messages/listener/MemberKickedMessageListenerTest.java
  • src/test/java/com/howaboutus/backend/messages/listener/MemberLeftMessageListenerTest.java
  • src/test/java/com/howaboutus/backend/messages/service/MessageServiceTest.java
  • src/test/java/com/howaboutus/backend/messages/service/SystemMessageServiceTest.java
  • src/test/java/com/howaboutus/backend/realtime/service/RoomMemberBroadcasterTest.java
  • src/test/java/com/howaboutus/backend/realtime/service/RoomMessageBroadcasterTest.java

@sonarqubecloud

sonarqubecloud Bot commented Jun 8, 2026

Copy link
Copy Markdown

@parkjuyeong0312 parkjuyeong0312 merged commit 8db5a9b into dev Jun 8, 2026
4 checks passed
@parkjuyeong0312 parkjuyeong0312 deleted the refactor/mongo-message-payload branch June 8, 2026 12:21
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.

1 participant