Web Socket

WebSocket - SockJs

댕발바닥 2024. 3. 24. 20:22

 

WebSocket의 한계

  • 웹 소켓은 HTML5 이후에 나왔기에 HTML5 이전에 기술에는 적용이 어렵다.
  • Firefox, Chrome, Edge, Whale 과 같은 브루아저에서는 동작을 하지만, 모바일 크롬, IE에서는 WebSocket이 동작하지 않으며, 모든 클라이언트와 브라우저에서 WebSocket을 보장해주지 못한다.
  • Proxy 서버가 Upgrade 헤더를 해석하지 못할 수 있으며, 유휴 상태에서 자체적으로 connection을 종료시킬 수도 있다.

 

해결 방안

  • 이를 해결 하기 위해서는 WebSocket Emulation을 이용한다
  • 최초 WebSocket 연결을 시도하고, 실패 할 경우 HTTP Streaming, Long-polling 같은 HTTP 기반의 다른 기술로 전환하여 다시 연결을 시도하는것을 말한다.
  • 일반적으로 spring-SockJs, node-Socket.io를 사용한다.
  • SockJ는 어플리케이션이 WebSocket API를 사용하도록 허용하지만, 브라우저에서 WebSocket을 지원하지 않는 경우에 대안으로 어플리케이션의 코드를 변경할 필요 없이 런타임에 필요할 때 대체하는 것이다.

 

SockJs 구성

  • SockJs Protocol
  • SockJs javascript client: 브라우저에서 사용되는 클라이언트 라이브러리
  • SockJs Server 구현: Spring-websocket 모듈을 통해 제공
  • SockJs Java Client: Spring-websocket 모듈을 통해 제공 (spring v4.1~)

SockJS는 WebSocket이 지원되지않는 브루아저에서 동작할 수있게 다음 3가지 분류로 진행된다.

 

1. WebSocket

2. HTTP Streaming

3. HTTP Long Polling

 

WebSocket Emulation Process

 

info
preview

  • Socket Client는 서버의 정보를 얻기 위해 GET / info 를 호출한다 이는 서버가 WebSocket을 지원하는지, 전송과정에 Cookies 지원이 필요한지, Cors origin 정보등을 응답으로 전달받는다. 이후 전송 타입을 결정하게 된다.

 

모든 요청은 아래의 구조를 가지게 된다.

 

https://host:port/myApp/myEndpoint/{server-id}/{session-id}/{transport}

 

  • server-id : 클러스터에서 요청을 라우팅하는데 사용함
  • session-id: SockJs session에 소속하는 HTTP 요청과 연관성 있음
  • TRANSPORT: 전송 타입 (ex, websocket, xhr-streaming, xhr-polling)

wesocket

 

xhr_streaming
eventsource

 

필자는 몇가지 방식의 유형을 전송해보고 확인해보았다.

 

  • WebSocket 경우는 하나의 HTTP 핸드 쉐이킹이 필요하며 이후 메세지는 Socket을 통해 교환된다.
  • Ajax/xhr_streaming, Long polling은 서버의 메세지를 받기 위해 long-running 요청을 가지며, http post 요청을 날린다 long polling경우는 추가적으로 응답후 현재의 요청을 끝내며 둘은 거의 유사하다.

 

허용된 origins

Springframework 4.1.5를 기준으로 WebSocket 및 SockJS의 기본 동작은 동일한 Origin요청만 수락하는 것이다. 오리진의 모든 목록이나 특정 목록을 허용하는 것도 가능하다

 

  • 동일한 오리진 요청만 허용 (default)
    • 이 모드에서는  SockJS가 활성화되면 iframe HTTP 응답 헤더 X-Frame-Options가 'SameOrigin'으로 설정되며, JSONP 전송은 요청의 오리진 확인이 불가능하므로 비활성화된다. 따라서 이 모드가 활성화된 경우 IE 6, 7은 지원되지 않는다.
    •  
  • 지정된 Origin목록 허용
    • 이 모드에서는 지정된 Origin은 반드시 http:// or https://로 시작해야한다. 이 모드에서 SockJS가 활성화되면 iframe 전송이 비활성화되므로 IE 6 ~ 9까지는 지원되지 않는다.
    • 위의 코드는 지정된 Origin 목록 허용을 한 것이다.
    •  
  • 모든 Origin 허용
    • 이 모드를 사용하면 허가된 오리진 값으로써 '*'를 사용해야 한다. 이 모드에서는 모든 전송(Send)를 사용할 수 없다.

 

cors

필자 경우 localhost:8725로 cors origin허용을 8724만 한 서버에 접근하면 cors origin으로 인해 접근 불가를 확인했다.

 

Heartbeats

SockJS 프로토콜은 프록시가 연결이 끊겼다는 결론을 내리는 것을 방지하기 위해 서버가 Heartbeat 메세지를 보내도록 요구한다. Spring SockJS 구성에는 HeartbeatTime 빈도를 사용자 정의하는 데 사용할 수 있는 속성이 있다. 기본값은 해당 연결에 어떤 메세지도 없는 25초를 사용한다. 이 25초는 IETF 권고안을 따른다.

 

Heartbeats

  • 개발자도구 - 네트워크 - WebSocket - Message 탭을 눌러보면 WebSocket의 메세지가 나오는데 25s마다 h 문자가 하나씩 찍힌다.

 

 

참조

https://dev-gorany.tistory.com/224