Skip to content

Web Socket & STOMP 리서치

JongKeun Kim edited this page Jan 13, 2021 · 2 revisions

으쌰으쌰 채팅 기능을 구현하기 위해 Web Socket과 STOMP에 대해 리서치한 내용을 정리하였습니다. 수정할 부분이나 보충할만한 부분있다면 추가 바랍니다.


채팅 기능은 양방향 통신이 가능해야 한다.

우리가 익숙하게 받아들이던 채팅 기능은 클라이언트가 넘겨주는 데이터를 서버가 받아서 처리도 해야하고, 서버가 전송할만한 데이터가 생기면 클라이언트에게 전달도 해줘야하는 양방향 통신 구조가 필요합니다.

카카오톡을 생각해봅시다. 누군가 나에게 메세지를 보내면 내가 따로 부탁한 것도 아니지만 알림이 뜹니다. 너무나 자연스러운 상황이지만 HTTP의 요청-응답이라는 통신 방법을 놓고 생각해봅시다. HTTP 통신은 클라이언트에서 요청을 하면 서버에서 응답을 하는 방식으로 통신을 합니다. 이는 클라이언트에서 요청을 하지 않는다면 서버는 응답하고 싶은 데이터가 있어도 클라이언트가 요청하기 전까지는 전달할 수 없음을 의미합니다. 내가 요청하지도 않은 카톡 메세지가 오는 이 통신 방식은 HTTP 방식 안에서는 조금 낯선 흐름인 듯 합니다.


HTTP 통신에서의 양방향 통신

HTTP는 특성상 연결이 유지되지 않아서 서버에서 먼저 요청을 보내는 통신 방법은 불가능합니다. 대신 HTTP는 양방향 통신을 흉내낼 수 있는 방법을 모색했습니다.

  • Polling - 클라이언트에서 일정 주기마다 요청을 보내고 서버는 현재 상태를 바로 응답하는 방식

    img

    • c: 새로운 데이터 있니? s: 없엉 (5초 뒤) c: 새로운 데이터 있니? s: 없엉 (5초 뒤) c: 새로운 데이터 있니? s: 없다고 ㅅ..
    • 단점 : 서버에서 변화가 없더라도 매 요청마다 응답을 내려주기 때문에 불필요한 트래픽이 발생하게 됨
  • Long Polling - 클라이언트에서 요청을 보내고 서버에서는 이벤트가 발생했을 때 응답을 내려주고 클라이언트가 응답을 받았을 때 다시 다음 응답을 기다리는 요청을 보내는 방식

    img

    • c: 새로운 데이터 생기면 줄래? (데이터 생길 때까지 서버가 기다림) s: 여깄어 c: 받았다. 또 새로운 데이터 생기면 넘겨줘 (데이터 생길 때까지 서버가 기다림) ...
    • 단점 : 실시간 반응이 가능하고 polling에 비해서 불필요한 트래픽은 유발하지는 않지만 오히려 이벤트가 잦다면 순간적으로 과부하가 걸릴 수 있음 (polling의 문제가 여전히 발생할 수 있음)
  • Streaming - 이벤트가 발생했을 때 응답을 내려주는데 응답을 완료시키지 않고 계속 연결을 유지하는 방식

    img

    • c: 새로운 데이터 있으면 계속 넘겨줘 s: 옛다 s: 옛다 s: 옛다 ...
    • 단점 : Long Polling에 비해 다시 요청을 하지 않아도 되므로 효율적이지만, 연결시간이 길어질수록 연결의 유효성 관리의 부담 발생

또한, 이 방법들은 공통적으로 HTTP를 통해 통신하기 때문에 Request, Response 둘다 Header가 불필요하게 크다는 단점이 있습니다.

이를 이용하여 서버-클라이언트간의 양방향 통신을 구현할 수도 있게 되었습니다.


Web Socket?

웹 소켓(web socket)은 웹 서버와 웹 브라우저간 실시간 양방향 통신환경을 제공해주는 실시간 통신 기술로 HTML5에서 표준으로 등록되어 있으며 다음과 같은 특징을 갖습니다.

  • 양방향 통신(Full-Duplex)
    • 데이터 송수신을 동시에 처리할 수 있는 통신 방법
    • 클라이언트와 서버가 서로에게 원할 때 데이터를 주고 받을 수 있다.
  • 실시간 네트워킹(Real Time-Networking)
    • 웹 환경에서 연속된 데이터를 빠르게 노출 (ex. 채팅, 주식, ...)
    • 여러 단말기에 빠르게 데이터를 교환

요청-응답 방식을 따르는 HTTP와 다르게 양방향으로 통신이 가능하기 때문에 web socket을 이용하면 채팅, 증권 거래 정보, 위치기반, 구글 Docs 같이 양방향 통신이 가능하고 실시간 네트워킹이 가능한 동적인 기능을 구현할 수 있습니다.


웹소켓이 다른 소켓들과 다른점?

  • 웹소켓은 UTF-8 포맷의 메세지 스트림만 허용
  • 웹소켓은 HTTP를 기반으로 하면서, 양방향 통신에서 HTTP의 문제점을 해결하는 것만 목표로 하고 있음

웹 소켓 동작 방법

img

  1. HandShake - 클라이언트 요청

    GET /chat HTTP/1.1      --> HTTP 버전은 1.1 이상, 반드시 GET 방식이어야함.
    Host: server.example.com  --> 웹 소켓 서버 주소
    Upgrade: websocket      --> 현재 클라이언트, 서버, 전송 프로토콜 연결에서 다른 프로토콜로 업그레이드 or 변경하기 위한 규칙
    Connection: Upgrade     --> Upgrade 헤더 필드가 명시된 경우 Connection 헤더 필드에 Upgrade 옵션을 지정하여 전송해야함
    Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==  --> 클라이언트-서버 간 신원을 인증하기 위한 값
    Origin: http://example.com  --> 클라이언트 주소
    Sec-WebSocket-Protocol: chat, superchat.  -> 클라이언트가 요청하는 여러 서브 프로토콜(서버에서 여러 프로토콜 혹은 프로토콜 버전을 나눠서 서비스할 경우 필요한 정보)
    Sec-WebSocket-Version: 13  
    
  2. HandShake - 서버 응답

    HTTP/1.1 101 Switching Protocols    --> 101 Switching Protocols가 오면 웹 소켓이 연결됬음을 의미
    Connection: Upgrade
    Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo= --> 클라이언트-서버간 신원을 인증하기 위한 값
    
  3. 프로토콜이 ws로 변경되고 데이터를 주고 받음

    • 데이터 보안을 위해서 ssl을 적용한 wss 사용 가능
    • 웹소켓을 위한 별도의 포트는 없음, 기존 포트(http-80, https-443)를 사용
    • Message 라는 단위를 사용
      • 메세지에 포함될 수 있는 교환 가능한 메세지는 텍스트와 바이너리
      • Message: 여러 frame이 모여 구성하는 하나의 논리적 메세지 단위)
      • Frame: communication에서 가장 작은 단위의 데이터, 작은 헤더 + payload로 구성
      • 웹 소켓 통신에 사용되는 데이터는 UTF-8 인코딩
  4. close frame을 주고 받아 연결을 종료함


STOMP(Simple Text Oriented Message Protocol)

웹 소켓은 문자열들을 주고 받을 수 있게 해줄 뿐 HTTP와 다르게 형식이 정해져있지 않기 때문에 애플리케이션에서 해석하기 힘들다는 문제가 있습니다. 이를 위해 sub-protocol을 사용해서 주고 받는 메세지의 형태를 약속하여 사용하는 경우가 많은데 이러한 프로토콜이 STOMP입니다.

STOMP는 텍스트 기반의 메세징 프로토콜로 채팅 통신을 하기 위한 형식을 정의합니다. TCP 기반으로 작동하며, HTTP와 유사하게 간단히 정의되어 해석하기 편하다는 장점이 있습니다.

STOMP 프레임 구조는 아래와 같습니다.

COMMAND            -> 명령
header1:value1     -> 헤더
header2:value2

Body^@             -> 바디
  • 명령, 헤더, 바디로 구성
  • 명령 : CONNECT, SEND, SUBSCRIBE, DICONNECT ...
  • 헤더와 바디는 빈 라인으로 구분, 바디의 끝은 NULL 문자로 설정

Socket.io와 SockJS?

웹 소켓에는 치명적인 단점이 있습니다. HTML5 이상부터 지원하는 기술이기 때문에 HTML5을 지원하지 않는 브라우저에서는 지원이 되지 않는다는 점입니다. 이러한 미지원 브라우저에 대한 문제점을 해결하기 위해 나온 솔루션이 Socket.io와 SockJS입니다.

  • Socket.io(http://socket.io)
    • Node.js 기반으로 만들어진 기술로 자체 스팩으로 만들어진 socket.io 서버를 만들고 socket.io 클라이언트와 브라우저에 구애받지 않고 실시간 통신이 가능해짐
    • socket.io는 node.js 기반이기때문에 자바로 개발하는 것이 어려움
  • SockJS(http://sockjs.org)
    • Springframework에서 WebSocket을 지원 (스프링 메뉴얼에 webSocket 부분을 보면 위와 같은 브라우저 문제를 해결하기 위한 방법으로 SockJS를 솔루션으로 제시하고 있음)
    • 서버 개발시 스프링 설정에서 일반 webSocket 으로 통신할지 SockJS 호환으로 통신할지 결정할 수 있음
    • 클라이언트쪽은SockJS client를 통해 서버와 통신함

참고

Clone this wiki locally