T_era

Spring WebSocket 알림 기능 구현 및 테스트 경험 정리 본문

Programing/Spring

Spring WebSocket 알림 기능 구현 및 테스트 경험 정리

블스뜸 2025. 7. 9. 18:35

1. WebSocketConfig의 핵심 메서드

1) registerStompEndpoints

이 메서드는 클라이언트가 최초로 WebSocket 연결을 맺을 엔드포인트를 정의.

@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
    registry.addEndpoint("/ws")
            .setAllowedOriginPatterns("*")
            .withSockJS();
}

주요 속성 및 옵션

  • addEndpoint(String path)
    클라이언트가 연결할 엔드포인트 경로를 지정합.
    예: /ws → 클라이언트는 ws://서버주소/ws로 연결
  • setAllowedOrigins(String... origins)
    CORS 허용 도메인 지정.
    예: .setAllowedOrigins("http://localhost:3000")
    (Spring 5.3+에서는 보안상 * 사용이 제한됨)
  • setAllowedOriginPatterns(String... patterns)
    와일드카드(*)를 포함한 패턴으로 CORS 허용.
    예: .setAllowedOriginPatterns("*")
  • withSockJS()
    브라우저가 WebSocket을 지원하지 않을 때 fallback(롱폴링 등) 지원.
    실무에서는 거의 필수!
  • setHandshakeHandler(HandshakeHandler handler)
    핸드셰이크 커스텀 처리 가능
  • setInterceptors(HandshakeInterceptor... interceptors)
    연결 전후에 인증/로깅 등 인터셉터 추가 가능
  • 여러 엔드포인트 등록 가능
    예:
    registry.addEndpoint("/ws1").withSockJS();
    registry.addEndpoint("/ws2").withSockJS();
  • 보안이 필요한 경우, 특정 도메인만 허용
    예: .setAllowedOrigins("https://mydomain.com")

2) configureMessageBroker

이 메서드는 메시지 라우팅 규칙과 브로커 설정을 담당.

@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
    registry.enableSimpleBroker("/topic");
    registry.setApplicationDestinationPrefixes("/app");
}

주요 속성 및 옵션

  • enableSimpleBroker(String... destinationPrefixes)
    내장 브로커 활성화.
    예: /topic, /queue
    • /topic: publish/subscribe(1:N)
    • /queue: point-to-point(1:1, DM 등)
  • setApplicationDestinationPrefixes(String... prefixes)
    클라이언트가 서버로 메시지 보낼 때 사용할 prefix 지정
    예: /app
    → 클라이언트가 /app/hello로 메시지 전송 시, 서버의 @MessageMapping("hello")로 라우팅
  • enableStompBrokerRelay(...)
    외부 메시지 브로커(RabbitMQ, ActiveMQ 등)와 연동할 때 사용
    예:
  • registry.enableStompBrokerRelay("/topic", "/queue") .setRelayHost("localhost") .setRelayPort(61613);
  • setUserDestinationPrefix(String prefix)
    사용자별 1:1 메시지 전송 시 사용
    예: /user

실전 팁

  • 여러 prefix 동시 사용 가능
    예:
    registry.enableSimpleBroker("/topic", "/queue");
    registry.setApplicationDestinationPrefixes("/app", "/pub");
  • 외부 브로커 연동 시, 대용량 실시간 서비스에 적합

2. SimpMessagingTemplate의 다양한 활용법

SimpMessagingTemplate은 서버에서 클라이언트로 메시지를 전송할 때 사용하는 핵심 컴포넌트.

1) 기본 메시지 전송

messagingTemplate.convertAndSend("/topic/notification", message);
  • 해당 토픽을 구독 중인 모든 클라이언트에게 메시지 전송

2) 특정 사용자에게 1:1 메시지 전송

messagingTemplate.convertAndSendToUser(
    userId, // 세션ID 또는 사용자명
    "/queue/notification", // 목적지
    message
);
  • 클라이언트는 /user/queue/notification을 구독해야 함

3) 헤더 포함 메시지 전송

MessageHeaders headers = new MessageHeaders(Map.of("custom-header", "value"));
messagingTemplate.convertAndSend("/topic/notification", message, headers);

4) 전송 전 메시지 변환

messagingTemplate.convertAndSend("/topic/notification", myObject, myHeaders);
  • myObject는 Jackson 등으로 자동 변환되어 전송

5) @SendTo, @SendToUser 어노테이션 활용

컨트롤러에서 직접 반환값을 특정 토픽으로 전송할 수도 있음

@MessageMapping("/chat")
@SendTo("/topic/messages")
public ChatMessage send(ChatMessage message) {
    return message;
}

3. 기타 실무에서 유용한 WebSocket 설정/기능

  • @MessageExceptionHandler
    WebSocket 통신 중 발생하는 예외를 처리
  • @SubscribeMapping
    클라이언트가 구독할 때 최초 1회만 메시지 전송
  • @EventListener(ApplicationReadyEvent.class)
    서버 기동 시 자동으로 메시지 전송 등
  • WebSocketSession 관리
    세션별 인증, 연결/해제 이벤트 처리
  • Interceptor/HandshakeHandler
    JWT 인증, 커스텀 인증 등

4. Postman과 브라우저(WebSocket/SockJS) 테스트 차이

  • 브라우저+SockJS+STOMP:
    Spring 서버와 완벽 호환, 실시간 알림 테스트에 최적
  • Postman:
    STOMP 프레임을 직접 작성해야 하며, SockJS fallback 미지원, CORS/인증 문제 등으로 실전 테스트에 부적합

5. 결론

  • Spring WebSocket은 다양한 실시간 메시징 시나리오를 지원하며, 설정 옵션도 매우 풍부함
  • 실무에서는 브라우저 기반 SockJS+STOMP 조합으로 테스트하는 것이 가장 쉽고 확실
  • 다양한 SimpMessagingTemplate 기능을 활용하면, 1:1 알림, 그룹 알림, 헤더 커스텀 등 복잡한 요구사항도 쉽게 구현 가능