Skip to content

fix: 채팅 거래 요청이 실시간으로 전달되지 않던 문제 - #106

Merged
wlsdn020416 merged 45 commits into
developfrom
feature/chat-realtime-heartbeat
Sep 2, 2026
Merged

wlsdn020416 merged 45 commits into
developfrom
feature/chat-realtime-heartbeat

Conversation

@yeunyeuna

Copy link
Copy Markdown
Collaborator

📌 작업 내용

  • 거래 금액 설정 후 상대에게 거래 요청 카드가 실시간으로 안 뜨던 문제 수정 (거래 완료는 정상 → 새로고침해야 보임)
  • WebSocket STOMP 하트비트 활성화
  • 소켓 재연결 시 놓친 메시지 복구
  • 채팅 메시지 브로드캐스트를 트랜잭션 커밋 이후로 이동

🔍 주요 변경 사항

원인

enableSimpleBroker("/topic") 에 하트비트 설정이 없어 유휴 WebSocket이 프록시(Render 등)에 의해 조용히 끊김. 심플 브로커는 미접속 클라 메시지를 큐잉하지 않고, 재연결 시 놓친 메시지를 복구하지도 않음.
→ 거래 요청은 "요청자가 상대의 금액 책정을 기다리는" 이 플로우의 가장 긴 유휴 구간 직후에 도착 → 죽은 소켓에 떨어져 유실.
→ 거래 완료는 항상 방금 활동한 사람이 받는 구조라 소켓이 살아있음.

WebSocketConfig

  • setHeartbeatValue(10s/10s) + 전용 TaskScheduler 빈 추가

chatSocket.js

  • heartbeatIncoming/Outgoing: 10000, reconnectDelay: 3000 명시

ChatPage.js

  • connectChatRoom onConnect 에서 첫 연결은 건너뛰고, 재연결부터 catchUpAfterReconnect() 로 히스토리·거래 플로우 상태를 서버 기준으로 재조회

ChatMessagePublisher

  • convertAndSend 를 TransactionSynchronization.afterCommit 으로 이동 (저장은 호출자 트랜잭션 안 유지)
  • 롤백 시 유령 메시지 방지, 구독자가 아직 DB에 없는 행 참조 방지
  • 트랜잭션 없는 호출 경로는 즉시 발행(기존 동작 유지)

🧪 테스트

  • ./gradlew compileJava 성공
  • ChatServiceTest + TradeServiceTest 8건 통과 (두 테스트 모두 ChatMessagePublisher mock → afterCommit 변경 영향 없음 확인)
  • 프론트 node --check 통과
  • 실제 프록시 유휴 끊김 재현 E2E — 로컬 재현이 어려워 미수행. 배포 후 "요청자가 수 분 대기 → 상대가 금액 설정" 시나리오로 확인 필요

📸 결과

⚠️ 참고 사항

  • 배포 환경(Render) 기준 이슈라, 로컬에선 증상이 잘 안 보일 수 있음
  • Render 백엔드가 유휴로 슬립되면 모든 소켓이 죽는 것은 별개 문제 (keep-alive 핑 권장)

pooreunblue and others added 30 commits September 1, 2026 11:04
fix: update Dockerfile COPY paths for repo-root build context
pooreunblue and others added 15 commits September 1, 2026 17:04
feat: 요청 게시글 상세 조회 시 연관 데이터 조회 개선
chore: 프론트엔드 런타임 API 주소 설정 추가
ci: 커밋 기준 자동 배포 트리거 설정 추가
fix: Render 백엔드 Dockerfile 경로 수정
- 하트비트가 없으면 유휴 WebSocket이 프록시(Render 등)에 의해 조용히 끊기고,
  끊긴 사이 브로드캐스트된 메시지(거래 요청 카드 등)가 유실됨
- 서버: enableSimpleBroker에 setHeartbeatValue(10s/10s) + 전용 TaskScheduler
- 클라이언트: heartbeatIncoming/Outgoing 10s 명시, reconnectDelay 3s

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- 심플 브로커는 미접속 클라이언트 메시지를 큐잉하지 않으므로,
  재연결 직후 서버 상태 기준으로 히스토리와 거래 플로우를 다시 맞춤
- connectChatRoom onConnect에서 첫 연결은 건너뛰고 재연결부터
  catchUpAfterReconnect() 실행

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- 저장은 호출자 트랜잭션 안에서, convertAndSend는 afterCommit 동기화로 이동
- 커밋 전 발행 시 롤백되면 유령 메시지가 생기고, 구독자가 아직
  DB에 없는 행을 참조할 수 있었음
- 트랜잭션이 없는 호출 경로는 즉시 발행(기존 동작 유지)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@wlsdn020416
wlsdn020416 deleted the branch develop September 2, 2026 05:20
@wlsdn020416 wlsdn020416 closed this Sep 2, 2026
@yeunyeuna yeunyeuna reopened this Sep 2, 2026
@wlsdn020416
wlsdn020416 merged commit 3139652 into develop Sep 2, 2026
6 checks passed
@wlsdn020416
wlsdn020416 deleted the feature/chat-realtime-heartbeat branch September 3, 2026 00:18
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.

3 participants