이번 프로젝트에서 핵심 기능은 서버(Java 컨테이너) 쪽에서 클라이언트(각 브라우져)들에게 특정 이벤트가 발생했을 때 5초 내에 알림을 주는 것이다.(팝업/경보 소리 등.)
보통은 Ajax를 써서 주기적으로 Polling 해오거나, 페이지 리로딩 하는 방식으로 하지만, 5초내에 응답을 해줘야 한다는 제약 사항 때문에 Pollong 하게 되면 열린 브라우져만큼의 적어도 5초에 1번씩의 부하가 서버에 전달되기 때문에 엄청난 트레픽 낭비일뿐 아니라 비효율적이다.(또한 거의 발생하지 않는 이벤트이다.)
그래서 Polling 하지 않고 구현하려면 어떻게 해야 할까 생각해 보았다.
1. 서버에서 이벤트 감지를 할 수 있어야 하고,
2. 서버에서 자신에게 붙어있는 클라이언트들의 리스트를 알아야 하고
3. 서버에서 클라이언트들에게 메세지를 전달할 수 있어야 한다.
그렇게 서버 푸시에 관련된 자료를 찾다가 매우 유용한 라이브러리를 알게 되었다. 바로 DWR(Direct Web Remoting)이다!!
DWR의 홈페이지(http://directwebremoting.org/)에서 보면 DWR을 이렇게 설명하고있다.
DWR is a Java library that enables Java on the server and JavaScript in a browser to interact and call each other as simply as possible.
즉, 서버의 자바 서블릿과 브라우져의 자바스크립트가 서로 상호작용 할 수 있다는 말이다!!
정말 놀라웠다!!ㅋ
실제로 테스트하면서 아래의 사이트를 참고하였다.
자바 개발자를 위한 Ajax: Jetty와 Direct Web Remoting을 사용하여 확장 가능한 Comet 애플리케이션 개발하기
https://www.ibm.com/developerworks/kr/library/j-jettydwr/
기본구조는 IBM의 자료를 참고하면서 DWR의 개념과 작동원리는 다른 여러 블러그와 카페, DWR의 홈페이지에서 얻었다.
특히 IBM의 자료는 DWR의 Reverse Ajax 기능과 Jetty의 Continuations의 기능이 잘 설명이 되어있다.
그런데 아무리 IBM의 자료 되로 해도 동작을 하지 않아서 많이 고생했다..
(다른 분들은 금방 쉽게 잘하신 것 같던데…OTL)
문제는 ReverseAjaxTracker 클래스에 있었다..
기존코드 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
... private ServerContext sctx; public ReverseAjaxTracker() { WebContext wctx = WebContextFactory.get(); sctx = ServerContextFactory.get(wctx.getServletContext()); RandomWalkGenerator.getInstance().addListener(this); } public void onCoord(GpsCoord gpsCoord) { ScriptBuffer script = new ScriptBuffer(); script.appendScript("updateCoordinate(").appendData(gpsCoord).appendScript(");"); // Push change out to clients viewing the page Collection<ScriptSession> sessions = new HashSet<ScriptSession>(); sessions.addAll(sctx.getScriptSessionsByPage(trackerPageUrl)); System.out.println(sessions.size()); for (ScriptSession session : sessions) { session.addScript(script); } } ... |
위와 같이하면 sessions의 개수가 자꾸 ‘0’이 나와서 동작하지 않는다..
그래서 아래와 같이 수정했다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
... private WebContext webContext; private ServletContext servletContext; private ServerContext serverContext; public ReverseAjaxTracker() { webContext = WebContextFactory.get(); servletContext = webContext.getServletContext(); serverContext = ServerContextFactory.get(servletContext); RandomWalkGenerator.getInstance().addListener(this); } public void onCoord(GpsCoord gpsCoord) { String contextPath = servletContext.getContextPath(); if (contextPath != null) { Collection<ScriptSession> sessions = serverContext.getScriptSessionsByPage(contextPath + "/dwr-tracker.html"); System.out.println("Collection<ScriptSession> sessions : " + sessions.size()); ScriptProxy proxy = new ScriptProxy(sessions); proxy.addFunctionCall("updateCoordinate", gpsCoord); } } ... |
위와 같이 하니까 잘 동작했다..ㅠㅠ
이번 프로젝트는 좀 신선한 도전으로 많은 시도를 해보려고 한다.
간단하게 주요 키워드들을 생각해보면 아래 정도가 될 것 같다.
Maven, GIT, Hudson, Junit, Spring2.5, iBatis, Tiles, Jetty, Extis, DWR(Comet, Reverse Ajax), Oracle, Mysql