NDC 참관기: 실시간 HTTP 양방향 통신

수요일(2012-04-25) 오후에 있었던 이승재 군의 발표.

발표 자료는 http://ricanet.com/new/view.php?id=blog/120425 에서.

HTTP Protocol의 한계

http는 request/response protocol이다. 이로 인해서 클라이언트 쪽의 이벤트는
서버 쪽에 쉽게 전달할 수 있지만, 서버 쪽의 이벤트는 클라이언트가 요청하기
전에는 전달할 수 없다.

그런데 현재의 웹 쪽 트렌드를 보자면, twitter나 facebook, google mail (or talk)
같은 경우 실시간으로 메시지를 보낸다. 어떻게 하는걸까?

이를 극복하기 위한 기법들

기본적으로 꼼수다 — 프로토콜의 한계 때문에.

Polling

웹 브라우저에서 주기적으로 요청을 보낸다. (클라이언트 쪽 타이머 이용)
문제:

  • 트래픽이 많다 / 서버 쪽 부하가 걸린다
  • 지연 시간이 크다; 이벤트-클라이언트 요청 시간 차이 때문에. 그렇다고지연 시간을 줄이면 트래픽/서버 부하가 더 커진다.

Long-polling

클라이언트가 미리 요청을 보내고, 서버는 이벤트가 생기는 순간까지 기다렸다가
이를 모아서 (이미 온 요청에) 응답을 보낸다.
Facebook 메신저 구현이 이를 이용한다.
문제:

  • 구현 복잡도. 서버가 요청이 이미 와 있는 경우와 그렇지 않은 경우를 구분해서 처리해야하는 등.
  • 지연 시간; 응답을 보낸 후 클라이언트가 다시 요청을 보내올 때까지의 시차.

Hidden iframe

페이지에 숨겨 놓은 iframe을 통해서 메시지를 계속 흘려 보낸다. (서버가 응답을
끝내지 않는다) 그래서 http streaming이라고 부르기도 한다.
Gmail messenger(=google talk)에서 사용하는 방법이다.

문제:

  • 응답이 끝나지 않기 때문에 클라이언트 쪽 웹 브라우저에 메모리 릭이 생긴다.
  • 프록시 / 보안 프로그램이 응답이 완전히 끝나야만 이를 넘겨주는 경우가 있다.

Browser plugin

Flash, ActiveX 등을 이용. 사실 상 TCP 소켓처럼 쓸 수 있다.
호환성 문제가 너무 커서…

WebSocket (html5)

javascript 단에서 진짜 소켓을 쓸 수 있다. 표준화가 아직이라 (protocol은
결정되었지만, API가 아직 unstable).
기존 웹브라우저와의 호환성 문제.

WebIRC (=IRC web-bridge for smartphones) 만들기

Long-polling이 호환성이 좋고 (최소한 iOS, android를 지원해야 했음),
구현이 재밌어 보여서(…) 이를 구현함.

프로토콜

  • InitLog: 각 채널 최근 로그 k 줄을 요청
  • UpdateLog(last\[\]): 각 채널에서내가 마지막으로 받은 로그 ID가 last일 때 그 이후 로그를 요청

서버 구현 이슈

HTTP 핸들러가 새로운 내용이 없으면 대기하는 것.
vs.
Event listener가 새로운 내용이 왔을 때 대기 중인 스레드(의 요청)를 깨우는 것
사이의 레이스 컨디션.[1]

node.js 류를 사용하면 오히려 쉬웠을지도 모르지만 이미 python으로 구현.

Webserver Architecture

동시에 살아있는 연결이 많아서,

  • 커넥션 당 1 스레드 때문에 메모리 병목
  • 고전적인 웹 서버의 경우 더 중요한 페이지 뷰보다 동시 접속 수가 문제
  • Gevent로 쉽게 해결
  • Long-polling에 맞춰서 구현했더니 stateless 프로토콜이 되어 네트워크 단절에 강해졌다.
  • 채팅 보내는 것이 네트워크 불안정엔 약했음. 이걸 극복하려니 사실상 TCP 류의 프로토콜을 HTTP 위에 재구현하는 형태가 되어버리게 되서…

Middlewares

앞에서 언급한 방법들엔 정답이 없다. 각 방법의 장단점이 다름.

orbited2, socket.io 같은 미들웨어가 있다.
그렇지만 정작 제작 시점에 사용하려던 orbited 사이트가 내려가 있어서
long-polling을 직접 구현.

Orbited

orbited.js + *application.js* — orbited server — application server

위의 형태로 구성. Web-router + firewall의 역할. Legacy TCP 응용프로그램
서버인 경우에도 쉽게 통신할 수 있다.

socket.io

nopde.js 기반. 메시지 단위 전송을 지원한다.

확인해야 할 사항

  • 연결 당 서버 리소스 소모량
  • 연결이 불안정하면 어떻게 되는가?
  • 웹 브라우저를 껐다켜도 괜찮은가?

웹-게임 연동

이런 기술을 쓰면 웹 게임에서도 네트워크 제약(http 문제)이 *거의* 없어진다.

WoW 전정실, 아이온, 마비의 거래소, 넥슨 홈이나 스팀의 업적 시스템 구현이라거나,
게임 웹 채팅, 친구 게임 참여 알리기, 우편 도착 알림 등의 실시간 기능이 가능해질듯.

결론(?): 취미 프로젝트 좋아요(…)

  1. 내 생각, 그리고 최치선 군의 의견을 조합하자면, 저건 pthread condvar 류의 동기화 도구를 사용하면 해결 될듯 함. 치선 군이 실 서비스에서 사용하고 있는 추천 구현체는 gevent의 Queue (monkey-patching하는). []

Published by

rein

나는 ...

12 thoughts on “NDC 참관기: 실시간 HTTP 양방향 통신”

      1. https도 사실상 암호화 안된거나 다름없다는게 문제가 되지 않을까요…

        PC에선 텍스트로 다 보이니 ..

        1. https는 SSL 설정만 제대로 되어있다면 충분히 강력합니다.

          암호화 채널의 양쪽 끝에서 암호화가 풀리지 않으면 좀 곤란하지 않을까요 (…)

          1. 물론 암호화를 당연히 해제 할 수 있어야 하지만…

            Fiddler같은 HTTPS 스니퍼의 존재로 인해 아무런 전문지식이 없어도 보고 변조가 가능하다는게 …

            1. 보안 쪽엔 문외한이라 속단하진 못하겠지만, https MITM 공격이 그렇게 쉽게 되진 않는데요.
              Fiddler로 스니핑을 하는건 CA cert를 속일 수 있거나 / 브라우저 류의 보안 부분을 잘 눌러놓거나 정도 밖에 없지 않나요?

  1. 저도 주로 꼼수를 사용하고 있는데 여기서 설명하는 polling, long-polling 기법인 듯 하네요. 머리 굴려서 열심히 만들었는데 결국 사람 생각하는거 다 거기서 거기 ㅋㅋ 이거랑 push notification server를 이용하면.. 어느정도 해결이 되더라구요.

    1. html5를 쓰거나 사도(?)에 해당할 만한 플러그인을 쓰지 않는한 가능한 범위가 거기서 거기니까 ㅋ

Leave a Reply