Web application에서 Server to Client통신

tw4204
VUNO SW Dev
Published in
7 min readSep 3, 2020

안녕하세요, 뷰노 SW개발팀의 김태완 입니다.

HTTP는 누구나 알다시피 단방향 통신입니다. 하지만, 웹 서비스를 만들다보면 server에서 client로 데이터를 보내야 하는 상황이 생깁니다.

  • 동일한 사용자가 로그인 했을 때, 기존에 로그인 된 client을 로그아웃 시켜야 하는 경우
  • 비동기적으로 실행되는 작업이 있을 때, 작업이 끝났다는 것을 client에게 알리는 경우
  • 기타 등등 …

이런 상황에서 사용할 수 있는 방법들에 대해 소개해보려고 합니다.

1. Polling

컴퓨터 공학에서의 polling은 컴퓨터(또는 장치)가 준비가 되었는 지를 확인하는 프로세스를 의미합니다. polling은 server가 client에게 데이터를 보내기(server push)보단 client가 server에게 데이터를 가져오는(client pull)것에 가깝습니다.

Polling

일정한 시간간격으로 client에서 server로 요청을 보내서, 원하는 event가 발생했는지 확인을 합니다. 만약 발생했다면 해당 데이터를 반환해줍니다.
polling은 구현하기 쉽다는 장점이 있지만, 매번 연결을 맺고 끊어야 한다는 단점이 있습니다.

2. Comet

코멧(comet)은 장시간 HTTP 요청을 대기하더라도 브라우저가 명시적으로 요청을 하지 않으면서 웹 브라우저가 데이터를 브라우저에 푸시할 수 있게 하는 웹 애플리케이션 모델이다. https://ko.wikipedia.org/wiki/%EC%BD%94%EB%A9%A7_(%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D)

comet을 구현한 기술들은 크게 두 가지 부류로 나뉩니다.

2.1. Streaming

스트리밍은 HTTP connection을 끊지 않고 계속해서 data를 전송하는 방식입니다.

  • Hidden iframe
    script 태그는 모든 내용을 받아와야지 실행이 됩니다. 즉, 요청이 완료가 되어야 script 태그내의 javascript 코드가 실행됩니다. 반면에 iframe은 요청이 완료되지 않아도 javascript 코드가 실행가능 합니다. 이를 이용해서 data를 streaming하는 방식을 hidden iframe이라고 합니다.
    이 방법은 data 전송에 있어서 header가 붙지 않는다는 점과 폭 넓은 호환이 된다는 장점이 있지만, 에러 처리가 안된다는 것과 브라우저의 메모리에 data가 계속 쌓인다는 단점이 있습니다.
  • XMLHttpRequest
    XMLHttpRequest는 fetch와 함께 AJAX(AsynchronousJavaScriptAndXML)의 대표적인 api입니다. XMLHttpRequest에는 readyState를 통해 통신의 진행상태를 확인합니다. readyState가 3이면 새로운 response가 왔다는 뜻이고, readyState가 4이면 요청이 끝났다는 의미입니다. XMLHttpRequest를 사용하면 에러 처리도 가능하고, 헤더에도 접근할 수 있다는 장점이 있습니다. 하지만, 몇몇 브라우저에서 보안 상의 이유로 readyState가 3일 때 응답 결과에 접근을 허용하지 않는다는 단점이 있다.
function xhrStreaming(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('POST', url, true);
var lastSize;
xhr.onreadystatechange = function() {
var newTextReceived;
if(xhr.readyState > 2) {
newTextReceived =
xhr.responseText.
substring(lastSize);
lastSize =
xhr.responseText.length;
callback(newTextReceived);
}
if(xhr.readyState == 4) {
xhrStreaming(url, callback);
}
}
xhr.send(null);
}

2.2. Long Polling

Long polling은 client에서 보낸 요청에 대해, server가 event가 발생하기 전까지 응답을 안주고 기다리다가 event가 발생한 순간 data와 함께 응답을 주는 방식입니다. Long polling은 polling보다 서버에 더 많은 부하를 줄 수 있다는 단점이 있습니다.

Long Polling

3. SSE (Server Sent Event)

SSE(Server Sent Event)는 HTML5에서 처음 도입된 개념으로, 앞서 설명한 comet을 표준화한 기술이라고 할 수 있습니다. client에서 server로 연결 요청을 보내면 server에선 text/event-stream MIME type으로 response를 보냅니다. 그러면 client는 연결을 끊지 않고 다음 response가 오기를 기다리게 됩니다.
SSE는 HTTP기반이기 때문에 별 다른 라이브러리나 프로토콜이 필요없다는 장점이 있습니다. 대신에 server에서 client로 한 방향으로 밖에 통신을 할 수 없다는 단점이 있습니다.

SSE(Server Sent Event)

4. Web Socket

WebSocket은 하나의 TCP 연결 위에서 full-duplex한 통신을 할 수 있는 프로토콜입니다. 처음에 client와 server가 handshake를 한 후에, server든 client든 언제든지 message를 전송할 수 있습니다. 앞서 설명한 방법들과는 다르게WebSocket은 message를 주고 받을때 dataframe 형태로 주고 받습니다. dataframe 헤더가 일단 http 헤더보다 크기가 작아서 데이터를 주고 받는게 용이합니다. IE10 이전 버전은 호환이 안되는 단점은, socket.io라는 아주 훌륭한 라이브러리가 해결해줬습니다.

WebSocket

Conclusion

기존의 HTTP가 만족시키지 못했던 Server to Client통신 문제를 해결하기 위해 단순한 polling부터 가장 표준이 되는 WebSocket까지 다양한 해결 방법이 있었습니다. 결론적으로는 웬만하면 WebSocket을 사용하면 해결이 되지만, server와 client간의 통신이 드문 경우(예를 들어, 1시간에 한번 update가 필요한 경우)에는 새로운 연결을 만드는 비용보다 연결을 유지해놓는 비용이 크기 때문에 단순하게 polling을 사용하는게 더 바람직합니다.

reference

--

--