1. 2010년 10월 작성
웹이 진화하면서 실시간으로 응답을 받고 싶어하는Need가 요즘 들어서 강렬해졌다는 느낌을 받는다. 웹브라우져
에임베디드되는애플릿/실버라이트/플래쉬를이용한 실시간성이 아닌 자체 HTML 안에서 실시간성을 요구받고 있다.
Ajax의 출현은 웹의 획기적인 발전을 일으키게 되었고, 더욱 실시간 서비스에 대한 Need를 불러 일으켰다.
이런 Need가 Comet이라고 하는 기술을 만들게 되었고, HTML5의 WebSocket 까지 이어지게 되었다.
HTML5는 여전히 표준이 만들어지는 과정이기 때문에 WebSocket을 사용하기까지는 시간이 필요한데, 이런 상황
에서 현재 실무에서 쓸 수 있는 대안은 바로 이 Comet기술이다.
Comet 기술은 외국에서는 이미 많이 사용되고 있으며, 대표적으로구글과Facebook에서 사용하고 있다.
그림 1. Comet의 서비스 사례
Comet이 무엇이냐 라고 말하기 앞서서, 먼저 여러 이름으로 불리우는데, 먼저 이 이름들을 소개하고자 한다.
Ajax push, reverse Ajax, Tow-way-web, HTTP Streaming, HTTP server push, Asynchronous push 라고도불리기도 한
다. 이렇게 많이 불릴 정도로 다양한 말로 표현되고 있지만, 사실 하나의 관념에서 나왔기 때문에 이렇게 Comet
이라는 이름으로 쓰기 시작했다.
웹 서버가 웹 브라우져에게 이벤트가 발생할 때마다 이벤트 데이터를 전달하고, 웹 브라우져는 데이터가 돌아오
면 처리한다. 이 때, 웹 브라우져가 명시적으로 요청하는 형태가 아닌 일반적인 HTTP 연결보다 긴 HTTP 연결안
에서 이루어진다. 이런 웹 어플리케이션 연결 모델을 Comet이라고 한다.
웹 브라우져는 데이터가 바뀌었는지 일일이 요청할 필요가 없어서 서버의 부하를 줄이고, Latency와 Traffic을 조
금이나마 줄일 수 있는 방식을 의미한다.
웹 서버에서 Http Streaming과 Long Polling 방식으로 사용자에게 알려주고 싶은 실시간성 정보를 전달해주는 방
법을 Comet이라고 일반적으로 말한다. Ajax가 실제로 원했던 그림이라고 생각한다.
실시간의 Need에 대한 처리에 대해서 지금까지 어떻게 웹에서 구현해서 사용하고 있는지 살펴본다.
실시간 Event 를 웹 브라우져에 전달하는 방식 소개
기존에 실시간으로 보여주고 싶은 Need를 위해서 페이지를 몇 초에 한번씩 반복적으로 해당 페이지를호출하는
Refresh 하는 방식 혹은 Ajax 호출을 통한 방식을 사용했었다. (그림 2 참조. Synchorous/Asynchornous 방식의
차이를 제외하고는 개념은 같다.)
2. 이 방식은 웹 브라우져에서 계속 호출되기 때문에 실시간 성격이 강할 때, 웹 서버가 많이 부담을 가질 수 있으
며, Latency가 일부 생길 수 있다. 하지만, Event가 많이 발생되는 경우에는 이 방식을 사용하여 심플한 상태를
유지하기도 한다. 올해 2월에 오픈한 EA에서 만든 Lord of Ulitma라는 웹게임이이 방식을 사용하고 있다.
그림 2. 주기적인 Refresh 또는 Ajax 호출
서버의 부담을 줄이기 위해서 Piggyback 이라는 방식이 있는데, 일반적으로 사용하는 HTTP 연결을 하는 응답에
살짝 얹혀 보내는 방식을 의미한다. (그림 3 참조) Piggyback이라는 단어가 영어로 “업기, 목마타기, 업혀가다”라
는 의미가 잘 담겨 있다. 하지만 이 방식은 항상 Piggyback 처리에 신경을 써야 하다 보니, Client 코드 코드가
25% 이상 증가되고, 복잡성이 야기되는 단점이 있다.
그림 3. Piggyback 방식
다음은 Http Streaming 방식이다. 웹 브라우져에서끊기지 않는 HTTP 연결(Stream multipart/cuunked response) 을
3. 가지도록 하여, Event가 발생하자마자 바로 웹브라우져에게 실시간으로 알리는 방식을 의미한다. (그림 4 참조)
이렇게 하여, 실시간성을 보장할 수 있다는 특징이 있다. 하지만, 이 방식의 구현 중 하나가 이슈가 있는데,
Iframe을 이용하는 경우가 있다. 이는 HTML의 상태바에진행중이라는UI가 나타나고, 커서에 모래 시계(요청 중)가
보여서 사용자가 오해할 수 있는 소지가 있다. 또한 연결 자체가 항상 keep alive 상태가 되어야 하기 때문에 이
부분에 대한 처리가 많이 필요할 수 있다.
이 방식의 장점을 최대한 활용하기 위해서 Flash를 써서 이 방식을 구현할 수 있다. 네이버 캘린더의 약속 알림
이 이 방식을 사용했다.
그림 4. Streaming 방식
웹 브라우져에서 특정 주기(조금 긴 기간임, 보통 30초~1분) 마다 ajax로 Event 발생되었는지를 요청하다가
Event가 발생되었을 때, 바로 웹 브라우져에 전달하는 방식을 Long Polling 이라 한다. (그림 5 참조). 주기적인
요청 방식과 Streaming 방식의 중간 형태를 띄고 있다. Facebook의 웹 채팅과 일본 서비스의 오목/오셀로 게임,
옥션 서비스가 다음의 방식을 사용하고 있다.
그림 5. Long Polling 방식
4. Web Browser Web Server
특정 주기
Event
지금까지의 방식 중 Streaming과 Long Polling 방식을 모아 Comet 이라고 한다.
Comet 기술 중 가장 많이 사용하는 방식이 Long Polling이다. 이 이유는 가장 쉽고 가장 HTTP Connection 개수
제한에도 부딪히지 않기 때문에 많이 활용되고 있다.
Facebook의 채팅 서비스를 살펴본다. 통신 상으로 보면, 두 개의 채널을 사용하는데, 하나는 내가 말하는 내용을
전달하는데 사용되고, 다른 하나는 서버로부터 내가 혹은 상대방이 보낸 메시지를 받는데 사용한다. 두 채널 모
두 ajax로 연결되도록 해서, 필요한 call만 전달되도록 하였다.
웹 서버에서 웹 브라우져로 전달할 내용이 없을 때는 55초까지만 기다렸다가 Http connection을 종료하고 다시
Http connection 을 다시 연결하는 구조이다.
사실 기본적인 채팅/게임 서비스와 다를 것이 없는 가장 간단한 상태이지만, 꽤나 효과적이고 HTTP의 한계를 극
복하려고 하고 있다.
그림 6. Facebook 채팅 구현 내용
5. Framework 소개
Comet 기술에 대해서 직접 Servlet Container과 javascript(ajax)를 사용하여 구현하는 사례도 많다.
Comet 기술에 대한 많은 구현들이 이미 존재한다. Dojo와 Jetty 진영이 가장 활발한 활동을 하고 있는데, 대표
적인 프레임웍은 DWR (http://directwebremoting.org/dwr/index.html), cometD(http://cometd.org/) 을 들 수 있다.
특히 cometD는 Bayeux라는 표준을 구현한 구현체이다. Bayeux는 json기반으로 통신하고, 하나의 http 연결을 여
러 개의 channel로 message를 전달할 수 있는 방식을 정의하고 있다. message는 meta/event/polling 방식으로 나
누어서 편하게 쓸 수 있는 방법을 제공하고 있다.
Servlet Container 지원
웹 서버에서는 바로 이런 comet 방식에 대해서 적절히 지원할 필요가 있다.
기존 웹 서버(Tomcat의 AJP Connector)는 Request에 대해서 하나의 Connection을 맺고 하나의 Thread에서 처리
하는 방식 (Blocking IO/Thread per connection)은 이 Comet 기술에는 적합하지 않다. (그림 7 참조)
Thread가 굉장히 중요한 자원인데, 이 Thread의 개수가 한정되어 있다는 점이다.
그림 7. Blocking IO 모델 (기존)
6. Request에 대해서 Blocking하지 않도록 하고(Non-blocking IO/Thread per request), 높은 성능(NIO)을 취하는 방식
을 이용할 필요가 있다. 그래서 많은 Request가 들어오더라도 많이 받아줄 수 있도록 해야 했다. (그림 8 참조)
Jetty의 continuation는 10700 Concurrent requests를 처리할 수 있었고, 메모리는 57MB만 사용했다고 하며,
Tomcat의 Comet도 10000 request 이상을 처리했다고 한다.
그림 8. Non-Blocking IO 모델 (Comet 지원)
그래서 Servlet Container마다 이런 Blocking Thread의 한계적인 상황을 넘어서기 위해서 Non-Blocking Thread 동
작이 되도록 하는 comet 기술이 들어가 있다. Tomcat의 Comet, Jetty의 Continuation 기술들이 이런 Comet 기술
(비동기 요청)에 대한 Need를 수용하기 위해서 만들어졌다. 많은 Servlet Container들이 이런 고민들을 가지고 있
었고, 이 부분을 표준화하였다. 그 결과로 Servlet 3.0에 비동기 처리에 대한 요구사항으로 추가되었다. Servlet 3.0
의 2.3.3.3 Asynchoronous Processing에 추가되었고, State machine부분과비동기적으로 처리할 내용, API가 소개되
어 있다.
현재 Servlet 3.0을 구현한 Tomcat 7, Jetty 8 Beta가 발표되었고, 조만 간에 안정적인 버전으로 되어 많이 사용하
게 되리라 생각된다.
Comet 기술의 도전과 향후 과제
웹 브라우져 또는 브라우져 버전마다 Socket Limit이 있는데, 이 부분에 대한 고려를 잘 해야 하고, 브라우져마다
의 특성을 잘 살필 필요는 있다. 또한 Connection Failure에 대한 정책과 처리에 대한 고민이 필요하다.
서비스의 특성에 맞게 Ajax polling으로 갈지, Comet으로 써야할지 고민이 필요하다.
7. 그리고, Scalability에 대한 고민이 필요하다. 비동기 처리 방식을 쓴다고 하지만, 메모리가 가장 큰 이슈가 될 수
있다. 최적화된 GC 알고리즘과 튜닝이 필요하고, 메모리의 크기에도 성능에 많이 민감할 수 있다. 특히 Socket
관련된 IO(NIO)에 대한 정확한 이해와 활용이 필요하다. 사용자 Session을 어디서 관리하느냐도 중요한 부분이
될 것이다.
보안 공격에 취약할 수 있다. Apache Http 서버의 경우는 비동기 모드가 지원되지 않아서 Tomcat 을 바로 앞단
에 취하는 구조를 쓰일 수 있다.
마지막으로 코딩의 복잡성이 있을 수 있다. Framework 없이 Servlet Container에서 비동기 Servlet을 구현할 경우,
State machine 사용으로 인해서 State를 생각하면서 코딩해야 하기 때문에 그동안 Sequence 형태로 개발에 비해
서 복잡함을 느낄 수 있다.
참고 내용
1. 도서 “Comet과 리버스 Ajax 차세대 웹 트렌드”
2. Exploring Reverse AJAX블로그
http://gmapsdotnetcontrol.blogspot.com/2006/08/exploring-reverse-ajax-ajax.html