SpringBoot의 withSocketJS()는 필수일까

 

 

 

SpringBoot의 WithSocketJS 설정

SpringBoot 서버 구축 시, withSocketJS() 라는 함수 활성화 선택지가 있다. 그 영향력은 아래와 같다.

.withSocketJS()가 아닐 때 Client의 접근 (ft. React)

// in Spring

@Override
public void registerStompEndpoints(
        org.springframework.web.socket.config.annotation.StompEndpointRegistry registry) {
    registry.addEndpoint("/ws")
            .setAllowedOriginPatterns("*");
            // .withSockJS(); 
}
import { Client } from '@stomp/stompjs';

const stompClient = new Client({
            brokerURL: 'ws://localhost:8080/ws',
            onConnect: () => {
                setConnected(true);
                console.log('Connected');
                stompClient.subscribe(`/topic/${Id}`, message => {
                    const msg = JSON.parse(message.body);
                    setMessages(prevMessages => [...prevMessages, msg]);
                });
                stompClient.subscribe(`/queue/${userId}`, message => {
                    const msg = JSON.parse(message.body);
                    setMessages(prevMessages => [...prevMessages, msg]);
                });
            }
        })

Client가 ws:// 로 접근한다

 

 

.withSocketJS()가 활성되었을 때 Client의 접근 (ft. React)

// in Spring

@Override
public void registerStompEndpoints(
        org.springframework.web.socket.config.annotation.StompEndpointRegistry registry) {
    registry.addEndpoint("/ws")
            .setAllowedOriginPatterns("*")
            .withSockJS(); 
}
import SockJS from 'sockjs-client';
import { Client } from '@stomp/stompjs';


const socket = new SockJS('http://localhost:8080/ws');
       
const stompClient = new Client({
    webSocketFactory: () => socket,
    onConnect: () => {
        setConnected(true);
        console.log('Connected');
        stompClient.subscribe(`/topic/${Id}`, message => {
            const msg = JSON.parse(message.body);
            console.error('Topic: ' + msg);
            setMessages(prevMessages => [...prevMessages, msg]);
        });
        stompClient.subscribe(`/queue/${userId}`, message => {
            const msg = JSON.parse(message.body);
            console.error('Queue: ' + msg);
            setMessages(prevMessages => [...prevMessages, msg]);
        });
    }
});

Client가 http:// 로 접근한다

 

 

SocketJS의 목적

SocketJS는 클라이언트와 서버 간의 WebSocket 연결에 대해서, WebSoket을 지원하지 않는 브라우저 혹은 네트워크 환경에서도 양방향 통신이 가능하도록 fallBack 매커니즘을 제공하고자 하였다

이에 따라, 다음과 같은 프로토콜 흐름을 가지도록 설계되어있다

 

SockeJS를 통한 WebSocket 통신 방식

1. Client의 HTTP 요청

우선적으로 Client가 서버에 HTTP 요청을 보낸다

클라이언트가 WebSocket을 지원하고, WebSocket 연결을 시도하고자 한다면, Upgrade헤더를 포함시킨다.

HTTP 헤더에 Upgrade: websocket과 같은 정보를 포함시킬 수 있는 것이다.

 

2. Server의 WebSocket 연결 수락

Client가 보냈을 upgrade헤더를 보고, Client가 WebSocket 지원이 되고 있으며 업그레이드 요청을 했음을 인지한다

이후, HTTP 연결을 수락하여 WebSocket으로 업그레이드되고 이후 통신이 WebSocket 프로토콜로 이루어지게 된다

 

초기 연결은 HTTP로 시작하고, WebSocket 업그레이드가 실패한 경우 HTTP기반의 폴백 매커니즘으로 우회적인 통신이 적용되는 것.

 

 

SockeJS가 활성화되지 않은 WebSocket 통신

이에 비해, SocketJS를 사용하지 않는다면 다음과 같은 보다 직접적인 연결방식이 취하게 되어있다

 

처음부터 ws:// 와 같은 WebSocket 프로토콜을 통해 서버에 대한 직접 연결을 시도하고, 만약 연결이 실패한다면 앞선 SocketJS처럼 HTTP 폴백 기능이 제공되지 않는다. (실패로 끝)

 

 

(결론) SocketJS가 권장되는 케이스

"예측되지 않는 클라이언트 환경을 대비한 안정적인 Socket 연결을 가능토록 하고싶다"

WebSocket을 지원하지 않는 구형 브라우저 혹은 네트워크 환경에서 WebSocket 연결이 차단되는 경우가 우려된다든지, 고정되지 않은 다양한 환경에서 동작될 가능성이 있다든지, WebSocket은 쓸 수 없지만 실시간 기능이 필요하다면 '.withSocketJS()'가 유의미해진다

 

그러나, 현재 최신 브라우저와 모바일 Applicatin 등(대략 2012년~2013년 이후 버전들)은 WebSocket을 기본적으로 지원하므로, 해당 SockJS의 폴백 기능이 불필요하거나 추가적인 복잡성을 더할 수 있음을 인지하고 있으면 좋다.

 

 

Reference


https://github.com/sockjs/sockjs-client

 

GitHub - sockjs/sockjs-client: WebSocket emulation - Javascript client

WebSocket emulation - Javascript client. Contribute to sockjs/sockjs-client development by creating an account on GitHub.

github.com