WebSocketConfig 구현

PUROMANGA·2025년 5월 28일

기술스택

목록 보기
13/22

개요

@EnableWebSocketMessageBroker

이걸 붙이면 Spring은 다음을 해줘:

  • WebSocket 서버 역할을 수행할 준비 완료
    STOMP 프로토콜을 이용한 pub/sub 메시지 처리 구조를 구성
    WebSocketMessageBrokerConfigurer 구현체를 찾아서 실행

엔드포인트를 등록

코드

	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		registry.addEndpoint("/ws")
			.setAllowedOriginPatterns("*")
			.withSockJS();
	}
  • registry.addEndpoint("/ws")
    클라이언트가 웹소켓을 연결하려는 진입점을 /ws로 설정
    → 즉, JS 코드에서 new SockJS("/ws") 또는 new WebSocket("/ws") 식으로 접근함
  • .setAllowedOriginPatterns("")
    모든 도메인(origin)에서 이 엔드포인트에 접근 가능하게 허용 (CORS 설정)
    → 실제 운영에서는 "
    " 대신 특정 도메인만 허용하는 게 보안상 안전함
  • .withSockJS();
    SockJS를 활성화해서 웹소켓을 지원하지 않는 브라우저에서도 fallback(대체) 방식으로 통신 가능하게 함
    (예: 오래된 IE 브라우저에서 Ajax long-polling으로 동작)

메시지 라우팅 규칙

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

1️⃣ registry.setApplicationDestinationPrefixes("/pub")

👉 클라이언트가 서버에게 메시지를 보낼 때의 주소 접두어

즉, JS에서 stompClient.send("/pub/~~~")로 보내면
그건 서버 컨트롤러의 @MessageMapping("/~~~")으로 매핑됨
stompClient.send("/pub/chat/message", {}, JSON.stringify({...}))
===
@MessageMapping("/chat/message")
public void send(ChatMessage message) {
    // 여기로 연결됨
}

2️⃣ registry.enableSimpleBroker("/sub")

👉 서버가 클라이언트에게 메시지를 보낼 때 사용하는 경로 접두어

즉, 서버에서 convertAndSend("/sub/~~~")로 메시지를 보내면
클라이언트는 stompClient.subscribe("/sub/~~~")로 구독 가능
stompClient.subscribe("/sub/chat/room/1", (msg) => {
  console.log("받은 메시지", msg.body);
});

@MessageMapping이 붙은 메서드는?

✅ 클라이언트가 서버에게 "메시지를 보내는(pub)" 용도야.

@MessageMapping("/chat/{chatroomId}/message")

이건 클라이언트가 /pub/chat/1/message로 send 하면 동작하는 로직
그래서 "받는 것처럼 보이지만 실제론 요청 핸들링"이야

🧭 즉, 정리하자면

항목설명
@MessageMapping("/chat/{chatroomId}/message")클라이언트가 서버에게 보내는 경로 → pub
stompClient.send("/pub/chat/1/message", ...)클라이언트 → 서버 메시지 전송
messagingTemplate.convertAndSend("/sub/chat/room/1", ...)서버 → 모든 구독자(클라이언트)에게 메시지 push
stompClient.subscribe("/sub/chat/room/1")클라이언트가 실시간 수신하고 싶은 경로 등록

flow

🔌 구조 요약

🔸 1. 프론트에서 먼저 연결 시도

const socket = new SockJS("/ws"); // ← 소켓 연결 요청
const stompClient = Stomp.over(socket);

stompClient.connect({}, () => {
  console.log("WebSocket 연결 완료"); // ← 서버가 수락하면 연결 성립
});

브라우저(클라이언트)가 /ws 엔드포인트로 handshake 요청을 보내고
서버(Spring)가 이걸 받아서 WebSocket 연결을 수락하는 구조야.

🔸 2. 서버는 연결을 "받아주는 역할"

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws") // ← 프론트가 연결 요청할 경로
                .setAllowedOriginPatterns("*")
                .withSockJS();
    }
}

서버는 /ws로 연결 요청이 오면 "오케이 연결하자" 하고 수락만 해주는 거야.

출처

https://velog.io/@hiy7030/chatting-1

https://moonstal.tistory.com/173

0개의 댓글