양방향 통신방법

0. intro

브라우저와 서버는 기본적으로 무상태성과 비 연결성을 가진다.
그러나 경우에 따라 실시간으로 업데이트가 이루어져야 할 경우, 서로의 통신이 주기적으로 이루어져야 할 떄가 있다. (ex, 실시간 채팅)

그런 경우, 주기적인 통신의 방법으로 크게 4가지가 존재한다.

1. Polling

  • 클라이언트가 주기적으로 서버에게 데이터요청을 하고, 서버는 이에 대해 응답하는 방식이다.

    예를들어, 실시간 업데이트를 생각해보면 주기적으로 Ajax 요청을 날려서 서버에게 업데이트의 내용을 받아내는 방식이다.

  • Ajax 요청의 주기가 너무 짧으면, 서버가 그만큼 한 브라우저에 응답하는 양도 많아지므로 서버에 부담이 커진다.

  • 반대로 요청의 주기가 너무 길면, 브라우저에 보이고 있는 데이터의 신선도가 떨어지기 떄문에 효용적이지 못하다.

  • 추가적으로, 보낼 데이터가 없음에도 불구하고 연결이 계속 유지되기 때문에 서버의 리소스가 낭비된다.

2. Long polling

  • 필요에 따라서 연결이 유지되고 그 외에는 연결이 해지되는 방식이다.
  • 예를들어, http 2.0부터는 첫 html 파일을 받을 때 해당 문서가 파싱되고 필요한 추가 데이터가 필요할 경우 Ajax 요청으로 해당 내용을 받게 되는데
  • 이 전체적인 과정이 끝나기 전까지는 서버와의 연결이 유지가 되어있는 상태이다.
  • 그리고 나서 문서의 파싱이 끝나면 서버에게 종료됬음을 알리고, 서버로부터 응답 이벤트가 발생하면 서로의 연결이 끊어지게 된다.

3. Server-sent Events

  • HTML5의 표준안이다
  • 서버와 클라이언트가 첫 연결에 성공하면 서버는 이벤트 발생 주기별로 클라이언트에게 필요한 데이터를 자동전송이 가능하다.
  • 예를들어 주식시장과 같은 경우, 유저에게 실시간으로 차트정보를 보여줘야하는데 이때 Server-sent Events를 활용할 수 있다.
  • 참고로, 브라우저의 요청이 필요 없이 서버가 독자적으로 응답을 날리는 연결형태이다.
  • HTTP Content-type을 application/event-stream으로 지정해줘야 한다

4. web socket

  • HTML 5의 표준안이다

  • TCP/IP 스택 위에 구축되는 전송계층으로, http handshake과정 이후 연결이 완료되면 HTTP를 웹소켓 프로토콜로 스위칭한다.

  • 그 이후 만들어지는 ws(일반) wss(SSL) 소켓이 형성되고, 이 소켓을 통해 통신한다

웹소켓 요청이 이루어질때 만들어지는 초기 http request는 다음과 같다

// 만약 new WebSocket("wss://javascript.info/chat"); 코드를 통해 요청을 만들어 전송할 경우,

GET /chat
Host: javascript.info
Origin: https://javascript.info
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Key: Iv8io/9s+lYFgZWcXczP8Q==
Sec-WebSocket-Version: 13

위의 내용처럼, 서버에게 Upgrade라는 요청으로 웹소켓, 그리고 자신의 웹소켓 아이디인 key를 만들어 전달하는 것을 볼 수 있다.

  • 웹소켓에서 데이터를 전송할 때 보내는 메서드 .send()에는 텍스트나, 이진데이터만 전송이 가능하다.
  • 데이터를 전송할 때에는, 'frame' 이라고 하는 데이터 조각을 형성하여 보내지게 된다.
  • 또한, socket에는 자동으로 상대방의 인터넷이 늦어질 때를 대비해서 데이터를 축척하는 버퍼가 존재하기때문에 이것을 활용하면 버퍼가 비워질 때마다 데이터를 전송할 준비를 하게 만들 수 있다.
// 매 100ms마다 소켓객체의 버퍼를 확인하여 비워져 있을 때에만 소켓을 전송하게 된다.
setInterval(() => {
  if (socket.bufferedAmount == 0) {
    socket.send(moreData());
  }
}, 100);

좋은 웹페이지 즐겨찾기