PostIT

[Spring/Stomp] Spring stomp와 SockJs를 통한 웹소켓 구현하기, 그리고 장,단점 본문

Spring

[Spring/Stomp] Spring stomp와 SockJs를 통한 웹소켓 구현하기, 그리고 장,단점

shun10114 2017. 4. 9. 16:11

# Stomp와 SockJs를 통한 WebSocket 구현하기.


- 최근 수정일 : 2017.04.09


##1. 배경


최근 Websocket을 통해 chat과 message(알림)기능을 실시간으로 작동될 수 있게 구현하였습니다. Spring의 stomp와 sockjs를 이용하였는데, 버전 호환이나 보안, 서버에 부하 정도에 대한 지식이 부족해 관리를 어떻게 해야할지에 대한 의문이 생기기 시작하게 되었습니다. 그리하여 여러 정보를 찾아 공부하며 블로그로 남겨보고자 합니다.



##2. 키워드

### WebSocket이란?


웹소켓(WebSocket)은 하나의 TCP 접속에 전이중 통신 채널을 제공하는 컴퓨터 통신 프로토콜이다. 웹소켓 프로토콜은 2011년 IETF에 의해 RFC 6455로 표준화되었으며 웹 IDL의 웹소켓 API는 W3C에 의해 W3C 차세대 웹 표준기술로 확정(2014년 10월 28일)되었습니다.



### TCP란?


전송 제어 프로토콜(Transmission Control Protocol, TCP, 문화어: 전송조종규약)은 인터넷 프로토콜 스위트(IP)의 핵심 프로토콜 중 하나로, IP와 함께 TCP/IP라는 명칭으로도 널리 불린다. TCP는 근거리 통신망이나 인트라넷, 인터넷에 연결된 컴퓨터에서 실행되는 프로그램 간에 일련의 옥텟을 안정적으로, 순서대로, 에러없이 교환할 수 있게 한다. TCP는 전송 계층에 위치한다. 네트워크의 정보 전달을 통제하는 프로토콜이자 인터넷을 이루는 핵심 프로토콜의 하나로서 국제 인터넷 표준화 기구(IETF)의 RFC 793에 기술되어 있다.


TCP는 웹 브라우저들이 월드 와이드 웹에서 서버에 연결할 때 사용되며, 이메일 전송이나 파일 전송에도 사용된다.


TCP의 안정성을 필요로 하지 않는 애플리케이션의 경우 일반적으로 TCP 대신 비접속형 사용자 데이터그램 프로토콜(User Datagram Protocol)을 사용한다. 이것은 전달 확인 및 순차 보장 기능이 없는 대신 오버헤드가 작고 지연시간이 짧다는 장점이 있다.



### UDP란?


사용자 데이터그램 프로토콜(User Datagram Protocol, UDP)은 인터넷 프로토콜 스위트의 주요 프로토콜 가운데 하나이다. 1980년에 데이빗 리드가 설계하였고, 현재 IETF의 RFC 768로 표준으로 정의되어 있으며, TCP와 함께 데이터그램으로 알려진 단문 메시지를 교환하기 위해서 사용된다. UDP는 유니버설 데이터그램 프로토콜(Universal Datagram Protocol)이라고 일컫기도 한다.


UDP의 전송 방식은 너무 단순해서 서비스의 신뢰성이 낮고, 데이터그램 도착 순서가 바뀌거나, 중복되거나, 심지어는 통보 없이 누락시키기도 한다. UDP는 일반적으로 오류의 검사와 수정이 필요 없는 애플리케이션에서 수행할 것으로 가정한다.


UDP를 사용하는 네트워크 애플리케이션에는 도메인 이름 서비스 (DNS), IPTV, 음성 인터넷 프로토콜 (VoIP), TFTP, IP 터널, 그리고 많은 온라인 게임 등이 있다.



### HTML5란?


- Global 5대 표준 웹브라우저(IE,Chrome,Safari,Opera,Firfox)에서 공통 표준기술로 채택한 HTML버전으로  역사상 최초 브라우저간 표준화가 이루어진 HTML버전이다.

- PC O/S ,모바일 O/S 의 각종 브라우저에서 모두 지원하는 HTML 표준 스펙이다.

- W3C 차세대 웹 표준기술로 확정(2014년 10월 28일)되었다.

- HTML(Hyper Text Markup Language)을 표기하기 위한 마크업 언어의 최신버전명으로 이전버전의 표기법들에 비해 많이 간결하고 명확하며 다양한 확장 API제공을 통해 단순 HTML 문서구조 표현 언어가 아닌 새로운 차원의 WEB FrontEnd 개발기술로 평가된다.

- HTML5의 주요 기능은 각종 HTML태그를 이용해 HTML문서(Document)의 문서구조를 표현하는 전통적인 HTML기능과 각종 새로운 HTML5 API 제공을 통한 기존 웹기술로는 불가능했던 다양한 확장기능을 제공한다.

(HTML5 API는 Programming Interface만 제공하며 구현은 Javascript 언어를 통해 HTML5 API 제공 기능을 구체적으로 구현합니다.)

- Flash,Silverlight으로 대표되는 각종 웹브라우저 Plugin(ActiveX포함)을 대체하는 HTML5 Tag & API 들의 집합체이다.



##3. 내용

### WebSocket Schema





###Spring Stomp Schema



### WebSocket Overview


- WebSocket 프로토콜은 클라이언트와 서버간에 지속적인 양방향 통신을 설정하기 위해 HTTP 1.1 프로토콜로 확장합니다.


1. 클라이언트와 서버간에 통신 채널을 설정하려면 클라이언트가 서버로 HTTP 업그레이드 요청을 보내야합니다. 이를 WebSocket 프로토콜 핸드 셰이크라고합니다.


2. 만약, 서버가 연결을 업그레이드 할 수 있는 경우,  HTTP 101 응답을 요청한 클라이언트에 보냅니다. 이 시점에서 핸드 셰이크가 성공한 것으로 간주되고 서버와 클라이언트 간의 연결이 WebSocket 프로토콜로 업그레이드됩니다.

* 참고 : 클라이언트가 HTTP 101 응답을받는 즉시, 연결은 더 이상 HTTP와 연결되었다고 간주되지 않습니다.


3. 이제 메시지는 WebSocket 연결을 통해 서버와 클라이언트간에 양방향으로 흐를 수 있습니다.


4. 데이터 교환에 참여한 모든 참가자(Websocket 연결된 사람)는 다른 참가자에게 닫기 요청을 전송하여 WebSocket 연결을 종료하도록 요청할 수 있습니다



### WebSocket supported Browswer


HTML5에 WebSocket은 W3C 차세대 웹 표준기술로 확정(2014년 10월 28일)되었다.


- Websocket의 브라우저 지원 현황을 보자.



#### Socket.io(http://socket.io)


Node.js 기반으로 만들어진 기술로 자체 스팩으로 만들어진 socket.io 서버를 만들고 socket.io 클라이언트와 브라우저에 구애받지 않고 실시간 통신이 가능해진다. socket.io는 node.js 기반이기때문에 모든 코드가 javascript로 작성되어 있다. 서버, 클라이언트 모두 javascript 기반으로 개발하는 것이 기본이다. 그러다보니 자바 개발자들은 socket.io를 쓸 수 없다. 자바로 개발이 가능하게 해주는 방법이 몇가지 있긴한 것 같지만 역시 javascript 기반 솔루션은 javascript로 개발해야 문제발생을 줄일 수 있을 것이다.



#### SockJS(http://sockjs.org)


Springframework에서 WebSocket을 지원한다. 스프링 메뉴얼에 webSocket 부분을 보면 위와 같은 브라우저 문제를 해결하기 위한 방법으로 SockJS를 솔루션으로 제시한다. 역시 자체 스팩으로 webScoket 미지원 브라우저를 관리한다. 서버개발시 스프링 설정에서 일반 webSocket 으로 통신할지 SockJS 호환으로 통신할지 결정할 수 있다. 클라이언트쪽은SockJS client를 통해 서버와 통신한다.
- Spring SockJS



##4. 추가사항

- 필요한 보안 정책 : CORS

- Spring Secuirty - Token

Spring에 Stomp를 사용하면 Token 기반 인증을 지원합니다.


Spring Security OAuth는 JWT (JSON Web Token)를 포함한 토큰 기반 보안을 지원합니다. 이것은 이전 섹션에서 설명한 것처럼 WebSocket을 통한 STOMP 상호 작용을 포함한 웹 응용 프로그램의 인증 메커니즘으로 사용할 수 있습니다. 즉 쿠키 기반 세션을 통해 ID를 유지 관리 할 수 ​​있습니다.


동시에 쿠키 기반 세션은 서버 쪽 세션을 유지 관리하기를 원하지 않는 응용 프로그램이나 헤더를 인증에 사용하는 모바일 응용 프로그램에 항상 가장 적합한 것은 아닙니다.


WebSocket 프로토콜 RFC 6455는 WebSocket 핸드 셰이크 중에 서버가 클라이언트를 인증 할 수있는 특별한 방법을 규정하지 않습니다. 실제로 브라우저 클라이언트는 표준 인증 헤더 (즉, 기본 HTTP 인증) 또는 쿠키만을 사용할 수 있으며 예를 들어 맞춤 헤더를 제공 할 수 없습니다. 마찬가지로 SockJS 자바 스크립트 클라이언트는 SockJS 전송 요청으로 HTTP 헤더를 보내는 방법을 제공하지 않는다. sockjs-client issue 196을 보라. 대신에 토큰을 보내는 데 사용할 수있는 쿼리 매개 변수를 보낼 수는 있지만 그 자체의 단점이있다. 토큰이 실수로 서버 로그에 URL과 함께 기록 될 수 있습니다.


[노트]

위의 제한은 브라우저 기반 클라이언트에 대한 제한 사항이며 WebSocket 및 SockJS 요청으로 헤더를 보내는 것을 지원하는 Spring Java 기반 STOMP 클라이언트에는 적용되지 않습니다.


따라서 쿠키를 사용하지 않으려는 응용 프로그램에는 HTTP 프로토콜 수준의 인증을위한 좋은 대안이 없을 수 있습니다. 쿠키를 사용하는 대신 STOMP 메시징 프로토콜 수준에서 헤더를 사용하여 인증하는 것을 선호 할 수 있습니다. 이를 수행하는 2 가지 간단한 단계가 있습니다.



STOMP 클라이언트를 사용하여 연결시 인증 헤더를 전달하십시오.


1. 인증 인터셉터를 등록하고 ChannelInterceptor로 인증 헤더를 처리합니다.

2. 인터셉터는 CONNECT 메시지에서 사용자 헤더를 인증하고 설정해야합니다. Spring은 인증 된 사용자를 기록하고 저장하며, 동일한 세션에서 후속 STOMP 메시지와 연관시킵니다



##5. 결론

1) 보안

Spring Stomp와 SockJS 이용하여 웹소켓에 메세지를 구현해보았습니다. 저의 경우 Spring에 로그인된 유저를 통해, 메세지가 전달되는 기능으로 구현하였는데, 로그인 된 유저의 Token과 Session값이 Spring security를 통해 생성되어 SockJS를 통한 메세지 전달에 사용자 정보가 프로젝트의 사용자 세션과 일치되어 보안상의 문제 없이 해당 사용자에게 문제 없이 전달 될 수 있었습니다.


2) 오버헤드

웹 소켓은 가장 성공적인 http 프로콜을 기반으로 하지만, http프로토콜과는 전혀 다른 프로콜이라고 생각하면 좋을것 같습니다. 특히, 기존 http프로콜은 연결-요청-응답-종료 반복된 작업을 계속 하는 문제가 발생됩니다. Websocket은 이를 해결하기 위해 나온 기술 중 하나이며, 2014년 표준으로 채택되어 HTML5에서 Websocket protocol이 추가가 되었습니다. 

웹소켓은 http를 통해 연결요청을 전달합니다. 이러한 과정을 handshake라고 하며, http를 Websocket 프로토콜로 바꾸는 Protocol switching 작업을 진행합니다. 이 과정을 통해 새로운 소켓이 만들어지고, 이 소켓을 통해 양방향 통신이 가능하게 되는 것입니다. 기존의 연결되고, 종료되는 부분이 1번으로 줄어지게 되는 것이며, 그 연결하는 과정 속에서 전달되는 기본 Header(Encoding, charset, text, cookie 등)정보를 줄일 수 있는 장점이 생깁니다.


#### 네트워크 오버헤드 비교:

폴링(Polling) 방식:

요청/응답 헤더 데이터 용량: (871 Byte)

1. 1000명 *  헤더 데이터 용량  = 871,000  Byte

2. 10000명 *  헤더 데이터 용량  = 8,710,000  Byte

3. 100000명 *  헤더 데이터 용량  = 87,100,000 Byte


WebSocket 방식:

메시지 데이터 용량: (2 Byte)

1. 1000명 *   메시지 데이터 용량   = 2,000  Byte

2. 10000명 *   메시지 데이터 용량   = 20,000  Byte

3. 100000명 *   메시지 데이터 용량   = 200,000 Byte



## * 참조 사이트

http://adrenal.tistory.com/20
https://ko.wikipedia.org/wiki/
https://docs.oracle.com/cd/E55956_01/doc.11123/user_guide/content/general_websocket.html
-
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/websocket.html#websocket-stomp
http://mohwaproject.tistory.com/entry/%E3%85%81%E3%85%81%E3%85%81

Comments