최근에는 Real-time Serivce 즉, 실시간 서비스를 구축해야하는 상황이 생길때가 많다.
만약 어떤 클라이언트에서 특정 이벤트 (예를 들어, 다른 클라이언트로 메시지 전송) 가 발생했을 때
즉각적으로 서버단에서 다른 클라이언트로 해당 이벤트를 바로 전달하려면 어떻게 해야할까?
실시간 통신을 위해서 생각해볼 수 있는 방법은 폴링(Polling), SSE(Server-Sent-Event), WebSocket 이 3가지 이다.
그럼 이 3가지의 차이점은 무엇일까?
- 폴링(Polling)
- 일정 주기로 서버에 계속 request 하여 새로운 이벤트를 가져오는 방법
- SSE
- 클라이언트가 SSE 스트림을 통해 서버로부터 계속 데이터를 가져오는 방법
- Server to Client 로 단방향 통신
- WebSocket
- 처음 HTTP request를 통해서 Handshake 과정을 거쳐 TCP 통신으로 전환하는 방법
- Server to Client, Client to Server 로 양방향 통신가능
만약 폴링을 사용하여 실시간 통신을 구현하게 된다면
대부분이 Ajax 나 Fetch API 와 같은 기술을 사용해 브라우저단에서 서버에 주기적으로 데이터를 요청하고
response 받은 데이터를 비동기적으로 브라우저에 업데이트 하는 방식으로 실시간 통신을 구현할 것이다.
하지만, 이렇게 된다면 클라이언트의 수가 증가함에 따라서 서버에 부하가 크게 증가할 수가 있고
부하를 줄이기 위해서 request 의 텀을 길게 준다면 데이터를 가져오는 능력이 떨어지게 된다.
결국
위와 같은 비효율적인 상황이 발생하여, 최근에는 SSE 또는 WebSocket 과 같이
클라이언트와 연결을 종료하지 않고, 계속해서 통신을 하는 방법을 사용하는 추세이다.
SSE 와 WebSocket 은 처음에 HTTP Request 에 특정 header 를 포함하여 서버에 request를 보내고
폴링과 달리 response 후 연결을 종료하지 않고 Real-time 을 위한 다른 프로토콜로 변환한다.
SSE 는 HTTP request 의 Header 를 통해서 서버가 SSE Stream 을 만들도록 요청하고
해당 SSE Stream 을 구독 하므로써 서버로 부터 계속 데이터를 받을 수 있다.
(즉, SSE Stream 구독으로, 서버 -> 클라이언트 단방향 통신)
WebSocket 은 Header 에 웹 소켓 통신을 명시하여
서버와 클라이언트 간에 Handshake 과정을 통해서 TCP socket 기반 통신(ws)을 진행한다.
(즉, ws 을 통해, 서버 <-> 클라이언트 양방향 통신)
장고에서는 WebSocket 을 Channel 라이브러리를 통해 사용가능하며
첫 HTTP request 후에 routing 과 consumer 를 통해서 ws 프로토콜로 변경하여 통신한다.