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 Jinuk Kim

SW Engineer / gamer / bookworm / atheist

Join the Conversation

12 Comments

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

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

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

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

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

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

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

  1. 아… 이거 발표하신분이 웹쉐어 만드셧던 분이구나….

    부럽다 넥슨 ㅡ,.ㅡ

    1. WebShare 제작자들은 N모사 들에 골고루 퍼져있습니다만 (…). 벤쳐에도 있지만 (…)

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

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

Leave a comment

Leave a Reply