Skip to content

feat: clientMessageId 기반 메시지 추적 및 운영 설정 정리#24

Merged
minsu11 merged 7 commits into
devfrom
fix-production-issues
May 15, 2026
Merged

feat: clientMessageId 기반 메시지 추적 및 운영 설정 정리#24
minsu11 merged 7 commits into
devfrom
fix-production-issues

Conversation

@minsu11

@minsu11 minsu11 commented May 15, 2026

Copy link
Copy Markdown
Owner

작업 개요

메시지 부하 테스트 과정에서 STOMP publish 시도 수만으로는 실제 메시지가 DB에 저장되었는지, WebSocket 구독자에게 정상 수신되었는지 정확히 검증하기 어렵다는 문제가 있었습니다.

이를 해결하기 위해 클라이언트가 생성한 clientMessageId를 메시지 요청/저장/응답 흐름에 반영하여, 메시지 단위로 다음 항목을 비교할 수 있도록 개선했습니다.

  • 클라이언트 publish 시도 수
  • DB chat_message.client_message_id 저장 수
  • WebSocket 수신 메시지 수
  • 중복 수신 여부
  • 누락 수신 여부
  • latency 측정

또한 배포 환경에서 사용하지 않는 설정 파일과 불필요한 폴더를 정리하고, 운영 환경 로그 레벨 및 WebSocket 관련 설정을 정리했습니다.


주요 변경 사항

1. 메시지 clientMessageId 반영

  • ChatSendRequestclientMessageId 필드 추가
  • ChatMessage 저장 시 client_message_id 컬럼에 값 반영
  • ChatMessageResponseclientMessageId 포함
  • 메시지 조회/응답 매핑 과정에서 clientMessageId가 함께 내려가도록 수정

이를 통해 부하 테스트에서 메시지 1건 단위로 publish, DB 저장, WebSocket 수신 여부를 추적할 수 있습니다.


2. 부하 테스트 검증 기반 개선

기존에는 메시지를 많이 publish했는지만 확인할 수 있었지만, 이번 변경 이후에는 clientMessageId를 기준으로 다음 흐름을 검증할 수 있습니다.

STOMP publish
→ 서버 메시지 저장
→ DB client_message_id 저장
→ WebSocket broadcast
→ 구독자 수신

이 방식으로 테스트하면 단순 발송량이 아니라, 메시지 단위의 저장 및 수신 정합성을 확인할 수 있습니다.


3. 운영 설정 정리

  • 운영 환경 yml 로그 레벨 정리
  • workflow 대상 브랜치에 현재 작업 브랜치 반영
  • WebSocket 경로 설정 변경에 따라 불필요한 web-dev, web-prod 설정 제거
  • 공통 web.yml 기준으로 설정 정리
  • 사용하지 않는 폴더 제거

테스트 및 검증

소규모 정합성 테스트

  • 사용자 수: 10명
  • 발신자 수: 2명
  • 테스트 시간: 30초
  • Publish: 58건
  • DB 저장: 58건
  • WebSocket 예상 수신: 580건
  • WebSocket 실제 수신: 580건
  • DB 저장 성공률: 100%
  • 수신 성공률: 100%
  • 중복 수신: 0건
  • 누락 수신: 0건

소규모 장시간 테스트

  • 사용자 수: 10명
  • 발신자 수: 2명
  • 테스트 시간: 180초
  • Publish: 356건
  • DB 저장: 356건
  • WebSocket 예상 수신: 3,560건
  • WebSocket 실제 수신: 3,560건
  • DB 저장 성공률: 100%
  • 수신 성공률: 100%
  • 중복 수신: 0건
  • 누락 수신: 0건
  • 평균 latency: 34.63ms
  • p95 latency: 61ms
  • p99 latency: 73ms

중간 부하 테스트

  • 사용자 수: 100명
  • 발신자 수: 10명
  • 테스트 시간: 60초
  • Publish: 1,190건
  • DB 저장: 1,190건
  • WebSocket 예상 수신: 119,000건
  • WebSocket 실제 수신: 119,000건
  • DB 저장 성공률: 100%
  • 수신 성공률: 100%
  • 중복 수신: 0건
  • 누락 수신: 0건
  • 평균 latency: 21,450.32ms
  • p95 latency: 39,225ms
  • p99 latency: 41,554ms

로컬 고부하 테스트

  • 사용자 수: 300명
  • 발신자 수: 10명
  • 테스트 시간: 60초
  • Publish: 590건
  • DB 저장: 590건
  • WebSocket 예상 수신: 177,000건
  • WebSocket 실제 수신: 177,000건
  • DB 저장 성공률: 100%
  • 수신 성공률: 100%
  • 중복 수신: 0건
  • 누락 수신: 0건
  • 평균 latency: 45,329.97ms
  • p95 latency: 86,037ms
  • p99 latency: 89,792ms

테스트 결과 해석

모든 테스트에서 clientMessageId 기준 DB 저장 성공률과 WebSocket 수신 성공률은 100%로 확인되었습니다.

특히 medium/high 테스트에서는 fan-out 규모가 커졌음에도 메시지 누락과 중복 수신은 발생하지 않았습니다.

다만 사용자 수와 fan-out 규모가 증가할수록 latency가 크게 증가했습니다.

  • smallLong: 평균 34.63ms
  • medium: 평균 21.45초
  • high: 평균 45.33초

이를 통해 현재 구조가 메시지 저장 및 전달 정합성은 유지하지만, 대규모 fan-out 상황에서는 WebSocket 브로드캐스트 처리량과 수신 처리 지연이 주요 병목이 될 수 있음을 확인했습니다.


테스트 과정에서 개선한 점

초기 medium 테스트에서는 발송 종료 후 5초만 대기하고 결과를 검증하여, 아직 수신 중인 메시지가 누락처럼 계산되는 문제가 있었습니다.

이를 해결하기 위해 발송 종료 후 다음 조건 중 하나가 만족될 때까지 기다리는 수신 안정화 대기 방식을 적용했습니다.

  • 기대 수신 수에 도달한 경우
  • 일정 시간 동안 수신 수가 증가하지 않는 경우
  • 최대 대기 시간을 초과한 경우

이후 동일 조건에서 재테스트한 결과, 예상 수신 수와 실제 수신 수가 일치하는 것을 확인했습니다.


확인한 점

  • clientMessageId 기준으로 메시지 publish 수와 DB 저장 수가 일치하는지 확인
  • WebSocket 구독자 수 기준 예상 수신 수와 실제 수신 수가 일치하는지 확인
  • 중복 수신과 누락 수신이 발생하지 않는지 확인
  • medium/high 테스트에서 fan-out 규모가 증가할수록 latency가 증가하는 것을 확인
  • 기존 5초 고정 대기 방식에서는 아직 수신 중인 메시지가 누락처럼 계산될 수 있어, 수신 안정화 대기 방식으로 테스트 기준 개선

주의 사항

  • clientMessageId는 기존 프론트 기능에서는 필수가 아니므로 nullable로 유지합니다.
  • 향후 메시지 재전송, optimistic UI, 중복 전송 방지, idempotency 처리로 확장할 수 있습니다.
  • clientMessageIdmessageType은 모두 String 타입이므로, ChatMessageResponse 생성자 호출 시 인자 순서가 뒤바뀌지 않도록 주의해야 합니다.

체크리스트

  • 메시지 요청 DTO에 clientMessageId 추가
  • 메시지 저장 시 client_message_id 반영
  • 메시지 응답 DTO에 clientMessageId 포함
  • 메시지 조회 응답 매핑에 clientMessageId 포함
  • 부하 테스트에서 DB 저장 수와 WebSocket 수신 수 검증
  • 운영 환경 yml/log 설정 정리
  • 불필요한 설정 파일 및 폴더 제거

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4e7c207c8c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +668 to +669
item.messageType(),
item.clientMessageId(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Pass ChatMessageResponse args in the declared order

ChatMessageResponse now declares clientMessageId before messageType, but this call still passes item.messageType() as the 3rd argument and item.clientMessageId() as the 4th. Because both are String, this compiles but swaps the fields at runtime, so clients receive an invalid message type (often a UUID-like client id) and cannot reliably route/render message payloads or correlate retries.

Useful? React with 👍 / 👎.

@minsu11 minsu11 changed the title Fix production issues feat: 메시지 clientMessageId 반영 및 운영 설정 정리 May 15, 2026
@minsu11 minsu11 changed the title feat: 메시지 clientMessageId 반영 및 운영 설정 정리 feat: clientMessageId 기반 메시지 추적 및 운영 설정 정리 May 15, 2026
@minsu11 minsu11 merged commit 9d79663 into dev May 15, 2026
1 check passed
@minsu11 minsu11 deleted the fix-production-issues branch May 15, 2026 16:39
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