웹소켓 (WebSocket)
이란 서버와 클라이언트간의 통신 프로토콜 중 하나로, 웹 애플리케이션 간 메세지 교환을 위해 사용된다.
일반적으로 소켓 (Socket)
이라고 함은 프로세스가 네트워크 상으로 데이터를 보내거나 받는 창구 역할을 하는데, 웹 애플리케이션 버전의 소켓이라고 이해하면 된다.
일반적으로 웹 애플리케이션에서 서버와 클라이언트의 소통을 위해 사용되는 프로토콜은 HTTP
이다. HTTP
프로토콜은 REST API
개발에서 사용되는데 STATELESS (무상태성)
한 성질을 가지고 있다는 특징이 있다.
이게 무슨 뜻이냐면, 클라이언트의 상태(데이터)를 서버가 가지고 있으면서 변화가 동적으로 추적되는 것이 아니라, 클라이언트의 요청에 따라 조건에 맞게 정해진 데이터를 반환한다는 것이다.
이것은 매우 효과적이고 효율적인 통신 방식이지만, 당연히 단점도 존재한다. 본질적으로 Stateful한 통신이 유리한 기능들이 존재하기 때문이다.
이러한 문제를 해결하기 위해 사용하는 것이 WebSocket
이다.
클라이언트는 일정한 주기로 서버에 요청을 보낸다. 서버는 데이터를 반환한다.
만약 답장이 왔다면 답장을 보내주고 답장이 안왔다면 업데이트된 데이터는 없을 것이다. 답장이 왔더라도 클라이언트 단에서 요청을 서버로 보내지 않는다면 답장은 받을 수 없다.
이것은 보이는 바와 같이 매우매우매우 비효율적인 방식이다.
우선 첫번째로, 수천명, 수만명이 참여하는 채팅창이 있다고 가정했을 때 서버는 매 주기마다 수천, 수만건의 요청을 처리해야 한다는 뜻이다.
이는 서버에 엄청나게 부담이 될것이다. 그로 인해 요청 주기를 길게 가져간다면 실시간성(real-time)이 떨어지게 된다.
Polling
의 단점을 가장 효율적으로 보완하는 방법은 아래와 같을 것이다.
서버에 요청을 보내고 업데이트가 있을 때까지 서버는 응답을 미루다가 업데이트가 발생할 때 서버로 부터 응답을 받는 것이다.
하지만 이 방식도 마찬가지로 수만명의 사용자가 존재한다고 가정하면 Polling
과 다를 바가 없어진다.
업데이트가 1초에도 수건씩 발생한다면 지속적으로 서버에 요청이 보내질 것이고 이는 서버의 큰 부담으로 이어진다.
마지막으로 스트리밍은 서버에 한번 요청을 보내면 그 이후로는 서버가 이벤트 발생 시 마다 응답을 지속해서 주는 것이다.
이 때 서버는 응답을 완료하지 않고, 연결 상태를 유지하며 계속해서 응답을 보낸다
일반적으로 아는 스트리밍 서비스에서 이용되는 방식이다.
이 방식의 단점은 결국 HTTP를 사용한 방식이기 때문에 요청이 보내진 후 서버로 부터 지속해서 응답을 받는 중이라면 연결을 끊고 다시 요청을 보내는 방식이 아니기 때문에 양방향 통신에는 적합하지 않다.
이러한 HTTP 통신의 한계를 보완하기 위해 등장한 것이 WebSocket
통신이다.
우선 클라이언트는 WebSocket 엔드포인트로 HTTP 요청을 보낸다. 이 요청을 Upgrade Request 라고 하는데, 웹소켓연결로 업그레이드를 요청하는 HTTP 요청이라는 뜻이다.
서버에서 웹소켓 통신을 연결한다는 뜻으로 101 응답을 준다. 이 때 서버에서는 사용자의 세션을 등록하고 이후에 연결이 끊어질 때까지 양방향 통신을 지속한다.
TCP Socket
은 바이트 스트림을 사용해 소통하지만, WebSocket
은 바이너리 데이터와 UTF-8 데이터를 둘 다 사용할 수 있다.HTTP 통신은 명확한 통신 규격을 따르기 때문에 어떤 형식의 요청이 오면 어떻게 처리할 지가 명확하다. 하지만 WebSocket
은 통신 프로토콜일 뿐 어떤 데이터가 어떻게 오고 가는지는 애플리케이션이 어떻게 해석하느냐에 달려있다.
그렇기 때문에 만약 UTF-8 텍스트 데이터를 보낸다면 시작과 끝에 0x00과 0xFF를 붙임으로써 텍스트임을 알려준다.
또는 이 메시지의 형태를 더 명확히 하기위해 sub-protocol
을 사용해서 '이 형태를 사용하자' 를 정한다.
sub-protocol로 가장 많이 사용되는 것이 STOMP (Simple Text Oriented Message Protocol)
로 채팅 통신을 하기 위한 형식을 정의한다.