Websocket 이 뭐죠? (이론편)

갈아만든배·2023년 7월 25일
0

websocket이 뭐죠?

목록 보기
1/1
post-thumbnail

사내 서비스에서 사용자 알림 기능을 구현할 때 웹 소켓을 사용하기에 이를 정리하고 이해해보려 한다.

웹 소켓이란?

웹 소켓이란 클라이언트와 서버가 http 프로토콜 안에서 전이중 통신을 할 수 있게 하는 통신 프로토콜이다.

전이중 통신이란, 양방향 통신 중에서도 동시에 보내면서 받을 수도 있는 통신을 말한다.

채팅방처럼 보내는 도중에 응답을 받을 수도 있는 그런 것을 떠올리면 된다.

위의 설명에서도 나오다시피 웹 소켓의 예제들은 주로 채팅 서비스를 구현하면서 많이들 공부하는데,
이는 웹 소켓의 전이중 통신 방식을 제일 잘 보여주는 것이 채팅 서비스 기능이기 때문이다.

꼭 채팅이 아니더라도 실시간 알림 같은 기능으로도 이용할 수 있다.

등장 배경(사실은 추측에 가깝다)

웹 서비스는 본래 사용자의 요청이 들어오면 해당 요청에 대한 응답을 전해주고 연결이 종료된다.

하지만 웹 서비스가 발전하면서 기존의 요청에 대한 응답만 전달할 것이 아니라 특정 이벤트에 대한 사용자 알림이나 실시간으로 특정 정보를 동기화해야 하는 기능이 요구되면서,
해당 요구 사항을 만족하기 위해서는 사용자가 특정 시간마다 계속 요청을 보내거나 특정 시간 동안 응답을 지연하되 해당 응답을 보내고 나면 곧바로 요청하는 식의 기술이 필요했다.

웹 소켓은 이러한 것을 소켓 통신의 형태를 통해 해결하려고 개발되지 않았나 추측하고 있다.

웹 "소켓"

웹 소켓은 말 그대로 http 통신 위에서 소켓 통신의 형태를 구현한 프로토콜이다.

당연히 통신 프로토콜로 TCP를 이용하고 있으며 첫 연결 시에 Handshake를 진행하여야 하며 통신 포트로 80번 포트(http)와 443 포트(https)를 같이 이용한다.
이 때문에 별도의 포트 설정은 하지 않아도 된다. (기본 포트를 사용한다는 가정 하에)

핸드쉐이크란 말 그대로 통신을 맺기 전 악수를 나누며 서로를 소개하는 인사같은 것이다.

대표적으로 TCP 통신 시 진행하는 3-Way hand shake가 있는데, 웹 소켓도 TCP를 사용하는 프로토콜이므로 웹 소켓만의 핸드쉐이크를 진행한 후 연결을 유지한다.

웹 소켓의 핸드쉐이크는 최초 연결을 요청하는 한 번의 http 요청과 해당 요청에 대한 응답으로 이루어진다.

최초 요청은 반드시 HTTP/1.1 버전 이상을 사용해야 하며, GET 메소드를 통해 요청하여야 한다.

MDN의 예제에 따르면 요청을 보내는 클라이언트는

GET /chat HTTP/1.1
Host: example.com:8000
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13

라는 내용으로 요청을 하는데,

이는 해당 요청을 받는 서버에 Connection 헤더와 Upgrade 헤더를 전달하며 연결을 웹 소켓으로 변경하자는 요청을 보내고 있음을 볼 수 있다.

서버는 이에 대한 답변으로

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

을 보내 해당 요청에 대한 응답을 한다.

이 때 웹 소켓 연결을 정상적으로 진행할 수 있을 경우 101 상태 코드를 전달하고, 어떠한 이유로 현재 웹 소켓 연결이 불가능할 경우 4XX 대의 상태 코드를 응답한다.

응답으로 101 코드를 전달받았을 경우, 웹 소켓이 연결되며 이후 웹 소켓을 통해 소켓 통신을 진행할 수 있다.

SockJS을 이용해보자

위의 내용을 통해 간략하게라도 웹 소켓이 어떤 것인지, 어떨 때 사용하는지에 대해 이해했을 것이다.

대충 양방향 통신이 필요할 때 쓰면 좋다는거잖아?

라고 이해했다면, 잘 이해했다고 말해주고 싶다.

그런데 갑자기 위에서 웹 소켓에 대해 잘 설명해놓고 뜬금없이 SockJS는 또 뭐냐고 물으려 한다면 잠깐만 기다려 주시라.

SockJS는 위에서 설명한 웹 소켓과 비슷한 객체를 구현해놓은 라이브러리이다.

왜 웹 소켓도 아니고 웹 소켓 비슷한 객체라고 설명하냐면,
기본적으로는 웹 소켓을 사용하지만 웹 소켓을 지원하지 않는 브라우저에 한해서는 웹 소켓이 아닌 다른 방식으로 웹 소켓 비슷한 기능을 제공해주는 라이브러리이기 때문이다.

해당 라이브러리를 사용하면 브라우저에서 해당 기능을 지원하는지에 대한 검증 없이도 웹 소켓을 통해 구현하고자 하는 기능을 구현할 수 있게 되는 것이다.

또한 SockJS는 Spring에서도 Configuration을 추가하여 간단하게 사용할 수 있으므로, 해당 라이브러리를 도입하기로 결정했다.

(사실 사내에서 이미 사용하고 있는 라이브러리라 사용하기로 결정했다)

STOMP는 또 뭐시당가

사내에서는 SockJS와 더불어 STOMP도 같이 사용하고 있는데 STOMP란,

Simple (or Streaming) Text Orientated Messaging Protocol

의 약자로 텍스트 기반 메시지 프로토콜을 뜻한다.

웹 소켓을 사용하면서 STOMP 또한 같이 사용하는 이유는 websocket은 텍스트와 바이너리 형식의 데이터를 통신하는 프로토콜이지만,
웹 소켓 프로토콜 내의 데이터에 대해서는 메시지를 어떠한 방식으로 보낼지, 메시지를 어떠한 방식으로 받는지에 대한 특정한 양식이 없다.

그렇기 때문에 서브 프로토콜로 STOMP를 같이 사용하여 메시지 처리 방식에 대한 규약을 정하는 것이다.

이제 왜 STOMP를 사용하는지에 대해 간단히 소개했으니 STOMP에 대해 간단하게 정리해보자.

STOMP는 Publish-Subscribe의 구조를 하고 있다.

보통의 socket 통신을 떠올리면 Server와 Client가 1:1로 맺어져 통신을 주고 받는 것을 떠올리는데,
STOMP는 이와 달리 사용자가 특정 경로를 구독하고 있으면 해당 경로로 보내진 메시지를 받아서 확인할 수 있는 구조이다.

요즘 널리 사용되는 정기 구독 시스템을 떠올리면 된다.

특정 잡지를 구독하고 있는 모든 사용자에게 해당 잡지가 배송되는 것처럼, 구독하고 있는 경로로 전달된 메시지는 모두에게 배송되어 읽어볼 수 있게 된다.

또한 pub/sub 구조로 이루어져 있어 중간에 메시지 브로커를 두어 메시지를 관리하기도 용이하고 구독 형식을 하고 있어서 해당 경로를 구독하고 있는 모든 사용자에게 broadcast를 보내기에도 수월하다.

이러한 특성 때문에 채팅 서비스로 예제를 많이 구현하는 것일 수도 있다.

또한 Spring에서도 STOMP에 대한 설정을 지원하고 있어서 메시지 브로커 설정만 해주면 쉽게 STOMP를 프로젝트에 적용할 수 있다.

이제 다음에 작성할 글을 통해, 구현 예제를 살펴보며 좀 더 자세히 파고들어보자.

0개의 댓글