Skip to content

[WebSocket] Heartbeat 인메모리 처리 및 배치 JWT 검증 시스템 구현 #117

@userjin2123

Description

@userjin2123

이슈 요약

하트비트 갱신 타이밍을 배치로 변경, 배치 때 JWT 토큰 검증하여 유효하지 않은 세션 제거

상세 설명

기존 문제

Heartbeat(10초)마다 모든 사용자가 Redis 호출 → 대규모 트래픽 시 Redis 부하
Redis 재시작 시 JWT 세션 소실 → WebSocket TCP 연결은 유지 → 인증 없는 유령 연결 발생

해결 방안

Heartbeat: 인메모리 lastActiveTime만 갱신 (Redis 호출 제거)
배치(30초): JWT 유효성 검증 후 Redis Pipeline으로 TTL 일괄 갱신
JWT 만료/소실 시: WebSocket 강제 종료 (CloseStatus 4001)

추후 더 변경 된 점
2026/01/28

  • WebSocketSessionHolder에 이미 웹소켓 세션이 있는데 이를 세션맵핑에 까지 저장하면 유지보수 복잡도 올라가고 SRP 위반이기에 Holder에서만 실제 웹소켓 세션 정보를 가지도록 변경

  • 웹소켓 서버가 비정상 종료되었을 때 레디스 Sorted Set에 콘텐츠별 시청 세션을 담는 곳에 시청자 수가 정리안되는 문제 발견, 재시작시 이를 해결하기 위해서 비정상 세션들 삭제

예상 효과

유저 1000명 기준: 분당 6000회 → 2회 Redis 호출

작업 항목

  • SessionMapping - record → class 변환, WebSocketSession 필드 추가, lastActiveTime volatile 추가
  • WebSocketSessionHolder - 신규 (WebSocket 연결~구독 사이 세션 임시 저장소)
  • WebSocketSessionDecorator - 신규 (연결/종료 시 Holder 등록/제거)
  • WebSocketConfig - configureWebSocketTransport()에 Decorator 등록
  • WatchingSessionRegistry - register() 시그니처 변경, getAllMappings() 추가, updateLastActiveTimeByWsSessionId() 추가
  • WatchingSessionEventListener - Holder에서 WebSocketSession 조회 후 register() 전달
  • WatchingSessionHeartbeatInterceptor - Redis 호출 제거, 인메모리만 갱신
  • WatchingSessionRepository - batchRefreshSessionTtl() 추가 (Pipeline 일괄 TTL 갱신)
  • WatchingSessionBatchRefresher - 신규 (30초 스케줄러, JWT 검증, 강제 종료)

Metadata

Metadata

Assignees

Labels

feat새로운 기능 추가

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions