[개념 설명] WebSocket

혜빈·2024년 8월 11일

보충내용

목록 보기
14/38
  • REST API, SOAP, GraphQL, gRPC 등은 주로 HTTP 기반이었음
  • HTTP에서는 클라이언트가 서버에게 요청을 보내고 서버가 그에 응하여 응답을 보내는 식으로 단방향 소통이 이루어짐
  • 서버가 클라이언트에게 메시지를 보내는 것은 클라이언트의 요청에 응답을 할 때 뿐임
  • 일반적인 기능들은 이러한 단방향 방식으로 구현이 가능함
  • 하지만 채팅 앱 같은 서비스는 불가능함
  • 내가 상대방에게 메시지를 보내는것은 클라이언트에서 서버로 통보하면 되는 것이기 때문에 가능하지만
    상대방이 메시지를 보냈을 때, 이를 나의 앱에서 감지하는것이 불가능함
    (HTTP/1.1 이하에서는 클라이언트의 요청 없이는 서버에서 메시지를 보내지 못하기 때문임)
  • HTTP를 사용해서 이 문제를 해결하기 위해서는 Polling이라는 방법이 있음
  • 클라이언트가 주기적으로 서버에 요청을 보내서 상대가 새로운 채팅을 보냈는지 확인하는 방법임
  • 서버는 업데이트가 있으면 있다고, 없으면 없다고 바로 응답을 보냄

Polling의 단점

  1. 요청을 보내는 주기만큼의 지연이 발생할 수 있음
  • 서버가 가지고 있는 상태의 변화에 즉각적으로 반응하지는 못함
  1. 계속해서 불필요한 요청들이 보내짐
  • 요청의 주기가 짧다면 반응속도는 빨라지겠지만 트래픽의 낭비가 심해짐

-> 개선하기 위해 Long Polling이 사용됨

Long Polling

  • 서버가 클라이언트의 요청에 바로 응답하지 않고 업데이트가 발생할 때까지 기다림

  • 그러다 상대방이 채팅을 보내거나 타임아웃으로 설정된 시간이 지나면 응답을 보내고, 클라이언트는 다시 요청을 보내서 다음 응답을 기다림

  • 이 방식을 사용하면 데이터의 업데이트에 반응하는 속도는 빨라지지만 서버의 부담이 커짐

  • 서버가 클라이언트로부터 요청을 받을 때부터 응답을 보내기까지 클라이언트와 의 연결이 지속되는데
    동시에 여러 클라이언트가 서비스를 사용한다면 그만큼의 연결을 유지해야 하므로 부하가 발생함 -> 업데이트에 대한 반응이 느려지는 결과로 나타나기도 함

  • 또한, HTTP에서의 요청과 응답에 포함되는 헤더 정보의 양도 매번 부담으로 작용함

  • 이러한 서비스를 제대로 구현하기 위해서는 클라이언트와 서버가 동등하게 메시지를 주고받을 수 있는 양방향 통신이 가능한 방식이 필요함! -> WebSoket


WebSocket 개념

  • HTTP/1.1이 클라이언트가 편지로 요청을 보내고 서버는 답장만 하는 방식이라면
    WebSocket은 서로가 자유롭게 대화를 주고받는 전화통화라고 볼 수 있음

  • HTTP/1.1 -> 편지

  • HTTP/2.0 -> 공중전화를 이용한 제한된 통화

  • WebSocket -> 스마트폰을 통한 자유로운 통화

WebSocket 통신과정

  1. 클라이언트에서 서버에게 WebSocket을 연결하자는 요청을 HTTP를 통해 보냄
    (전화통화를 하자는 내용의 편지를 보냄)

  2. 서버는 그것이 가능한 경우 이를 수락하는 응답을 HTTP로 보냄
    (이 과정을 Handshake라고 함)

  3. 연결이 이루어지만 그 때부터 클라이언트와 서버는 HTTP가 아닌 WebSocket 프로토콜을 사용하여 소통을 함
    (이 때부터 전화통화가 이루어짐)

  4. 클라이언트와 서버는 자유롭게 서로에게 메시지를 보낼 수 있음

  • WebSocket에서의 통신은 헤더의 크기가 작고 Overhead가 적기 때문에 HTTP보다 효율적인 통신이 가능함
  • 전화통화는 한 쪽이 다른 쪽에게 통화를 종료하자는 메시지를 보내기 전까지 지속됨
  • 한 쪽에 close 프레임을 보내면, 다른 쪽에서 이를 확인하고 close 프레임을 응답으로 보내고 연결이 종료됨

Handshake

  • 헤더는 우편물에 붙은 송장과 같음
GET /chat HTTP/1.1
Host: example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dgdjflgsarjwlkjedf==
Sec-WebSocket-Version: 13
  • Upgrade, Connection 부분은 현재의 HTTP 연결을 WebSocket 프로토콜로 업그레이드 하자는 내용임
    (지금부터 전화로 대화하자는 의미)
  • Sec-WebSocket-Key에는 클라이언트가 랜덤으로 생성한 값을 Base64로 인코딩한 문자열이 담김
  • 서버는 이 요청을 받고나서 GUID라고 불리우는 정해진 문자열을 그 키에 이어붙인 후 SHA-1 해시로 계산하여 다시 base64로 인코딩함
    (모두에게 알려진 어떤 공식을 통해 위의 Sec-WebSocket-Key의 문자열을 아래의 Sec-WebSocket-Accept 문자열로 바꿈)
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s4fCDSJKREWFDSLKADXDLFKS==
Sec-WebSocket-Version: 13
  • 서버는 이 값을 헤더에 담아 클라이언트에게 돌려보내고
    클라이언트는 이것이 자신이 보낸 키로부터 생성된 값이 맞는지 확인함
    (모두에게 알려진 공식이기 때문에 서버가 제대로 키를 처리했다는 것을 클라이언트도 확인 가능)
  • 이것으로 클라이언트는 응답이 자신이 요청을 보낸 상대로부터 온 것임을 확인하고, 둘은 자유롭게 양방향으로 소통할 수 있게 됨


비정상적인 종료 감지하는 방법들

  1. 지정된 시간동안 메시지가 없을 시 확인 패킷을 보내는 방법

  2. 주기적으로 ping pong 프레임을 주고받아서 서로의 접속여부를 확인하는 방법


  • WebSocket은 하나의 연결을 끝까지 유지하고, 그 과정에서도 적은 자원만 소모하기 때문에 Long Polling만큼 서버에 부담을 주지도 않음

  • WebSocket을 사용해서 채팅 앱과 같은 실시간으로 서버로부터의 업데이트가 필요한 서비스들을 효율적으로 구축할 수 있음

  • WebSocket에서의 통신은 TCP를 사용하기 때문에 데이터의 순서와 신뢰성이 보장됨

  • TCP: Transmission Control Protocol

  • 이와 같은 장점들 덕분에 WebSocket은 채팅 앱 뿐 아니라 온라인 게임, 주식 관련 앱, 협업 도구, 위치 추적 등 실시간 양방향 통신이 필요한 분야에 활용이 됨

WebSocket의 한계

  1. 서버의 설계에 따라 구현이 복잡해질 수 있음
  • 특히 로드 밸런싱이 적용된 서버에서는 이를 고려하고 설정할 부분이 많아짐

  • NGINX, HAProxy, AWS ELB 등 WebSocket을 처리할 수 있는 로드 밸런서를 선택하여 구성하는 등 서비스에 적합한 방법을 찾아 해결하면 됨


로드 밸런싱

  • 은행 상담창구처럼 서버 여러대가 클라이언트의 요청을 나눠서 받는 것
  • WebSocket은 특정 서버와의 지속적인 연결 안에서만 이루어지기 때문에
    한 서버와 WebSocket 통신을 시작하면 그 이후로도 계속 그 서버로만 데이터가 전송되도록 설정해야 함

  1. 메시지의 크기가 제한되어 있음
  • 브라우저, 서버, 네트워크 환경마다 WebSocket에서의 메시지 크기에 제약을 둘 수 있음
  • 대용량의 데이터의 경우, 분할해서 전송하거나 다른 프로토콜을 사용하는 등의 방법을 사용할 수 있음
  1. WebSocket의 기본 프로토콜인 WS는 통신이 암호화 되어있지 않음
  • 보안이 중요한 서비스라면 SSL/TLS 인증서를 발급받은 후 이를 사용하여 WSS를 설정해야 함
  1. WebSocket도 서버에 부담을 줌
  • Polling 등의 방식보다는 훨씬 덜하지만 그래도 서버에 부담을 줌
  • 많은 사용잘의 동시에 접속해 있을 수록 유지해야 하는 TCP 연결이 많아지고,
    메시지들이 오가는 빈도가 높다면 네트워크 대역폭과 CPU의 사용량도 증가함
  • 구현하고자 하는 서비스에 이러한 문제가 발생할 경우 WebSocket이 가장 적절한 선택인지 고려해봐야함
profile
최강 개발자를 꿈꾸는 병아리

0개의 댓글