Outsider's Dev Story

Stay Hungry. Stay Foolish. Don't Be Satisfied.
RetroTech 팟캐스트 44BITS 팟캐스트

2010 한국 자바 개발자 페스티벌 #2

이 포스팅은 2010 한국 자바 개발자 페스티벌 #1에서 이어진 포스팅입니다.



Jetty - Continuation - 이상민
Track 3의 두번째 세션입니다. 공식적으로는 Track간의 이동이 허용치 않았지만 자리의 여유도 있었고 해서 관심있는 세션으로 이동했습니다. Comet등을 이용할 때 필요한 Jetty서버의 Continuation에 대한 내용이었습니다.

일반적인 웹서버인 아파치 같은 경우는 쓰레드 기반이기 때문에 요청마다 쓰레드가 생성되지만 NGinX같은 경우는 이벤트 드리븐 방식이기 때문에 DDoS공격에 대한 대처로 NGinX와 Jetty 조합도 괜찮은 편입니다.

Jetty 발표자료발표하시는 이상민님

현재 많이 사용하는 Servlet Spec 2.5기반인 WAS들은(Tomcat 6은 2.5기반, Tomcat 5.5는 2.4기반) 쓰레드 풀을 사용하는데 이런 경우에 쓰레드플의 갯수를 어느 정도로 할 것인가 하는 것은 어려운 결정입니다. 커넥션을 연결할 때 하나의 쓰레드를 차지하게 되고 기본적으로 동기적(Synchronously)이고 이를 비동기적으로 만들기가 어렵기 때문에 일반적으로 풀링을 사용하거나 Ajax같은 경우로 연결할 때도 롱풀링같은 기술을 사용합니다. 서버는 모든 각 클라이언트마다 한개 이상의 쓰레드를 할당하게 됩니다.

Jetty Continuation
일반적으로 실무에서는 JEUSWebLogic를 사용하는데 Tomcat이나 Jetty도 성능이 좋습니다. 하지만 현업에서는 책임을 전가(?)할 대상이 필요하기 때문에 오픈소스보다는 상용을 선호합니다. Jetty는 버전 6과 7이 있는데 7부터는 Eclipse로 넘어갔습니다.

Jetty는 HTTP Server이고 javax.servlet container를 제공하며 Small Footprint(메모리를 아주 적게 사용한다는 의미)하며 비동기적(Asynchronous)합니다. Jetty가 사용하는 Asynchronous Servlets은 동기IO나 NIO를 사용하는 것과는 약간 다르고 Asynchronous Wait라고 생각하면 됩니다. Jetty의 Continuation은 Suspended되고 Restarted되는 구조입니다.

Continuation 흐름도

클라이언트가 요청을 하면 Servlet이나 Filter를 탄 후 suspend()가 호출되고 비동기적 호출(Async.call : 직접 구현해야 하는 부분입니다.)을 하게 됩니다. Async.call을 한 다음에는 클라이언트의 Connection은 끊기지 않은 상태에서 쓰레드는 반납이 되고 다른 요청을 받을 수 있게 됩니다. Async.call은 complete()되거나(종료) resume()되거나(되돌아옴) timeout이 발생(시간초과)하게 되고 다시 Servlet이나 Filter를 통해서 클라이언트에게 결과를 돌려주게 됩니다.

물론 이렇게 구현하여도 쓰레드를 새로 생성하는 것은 엄청난 비용이 들기 때문에 쓰레드풀은 계속 사용해야 합니다. 컨티뉴에이션을 이용하면 하나의 쓰레드가 많은 요청을 처리할 수 있게 되고 가장 많이 쓰이는 곳은 채팅입니다. Jetty에서는 QosFilter(Quality of Service Filter), DosFilter(Denial of Service Filter), GzipFilter(Compress response objects), ProxyServlet를 제공하고 있습니다.

Continuation Sample

하얀색으로 표시된 부분만 구현하면 되며 Continuation은 Interface이기 때문에 객체를 생성할 수 없고 Continuation continuation = ContinuationSupport.getContinuation(req);처럼 요청을 넘겨주고 Continuation의 인스턴스를 받아와야 합니다. continuation .addContinuationListener(new AListener);에서 리스너를 지정하고 setTimeout()으로 타임아웃을 밀리세컨드로 지정합니다. 여기서 타임아웃이 0보다 작거나 같으면 절대 expire가 되지 않기 때문에 절대 사용하면 안되고 이렇게 사용할 경우 Out of Memory 혹은 Thread Pool이 발생할 수 있습니다. continuation.suspend()를 호출한뒤에 asysnchronous call 부분에서 로직을 작성하고 resume()이나 complete()가 호출되면 종료되게 됩니다.(resume()은 suspende된 것을 다시 시작합니다.) 여기서 리스너는 ContinuationListener를 구현해야 하고 onComplete, onTimeout을 작성해야 합니다. onComplete는 종료시에 무조건 호출되며 onTimeout이 호출될 때도 onComplete가 같이 호출됩니다.

Servlet 3.0
2009년 12월 10일에 파이널 릴리즈가 되었으면 JSR 315를 따릅니다. Glassfish 3가 Servlet 3.0 기반으로 Sun에서는 사용은 공짜로 하지만 기술문의를 할 때는 요금을 지불해야 합니다. 테스트 결과 대부분의 경우에서는 Tomcat과 Jetty가 빠르고(Jetty가 약간 더 빠릅니다.) 특수한 경우에만 Glassfish가 빠른 것으로 나타났습니다. 최근 베타릴리즈된 Tomcat 7에서 Servlet 3.0을 지원하고 있습니다.

주요 특징으로는 비동기 서블릿과 Comet을 지원하고 Web Framework Pluggability하며 @WebServlet, @WebFilter, @WebInitParam, @WebListener, @MultipartConfig의 애노테이션을 지원하여 web.xml에 설정하지 않고 소스코드에서 바로 적용할 수 있습니다. java.servlet.asyncContext의 AsyncContext 인터페이스를 제공하고 있으면 Jetty와 용도는 같지만 메서드명은 약간 다른 setTimeout(), addListener, complete를 제공하고 있습니다. java.servlet.ServletRequest의 startAsync()를 호출해서 비동기를 시작할 수 있습니다.

Servlet 3.0에 대해서는 JavaOne에서 공개한 PDF에서 자세한 내용을 볼 수 있습니다.

올 초에 매쉬업준비하면서 윤군이 일부구현해서 Comet서버용으로 Jetty 테스트를 하면서 알게되었던 Continuation에 대한 부분에 대해서 따로 공부할 여유를 갖지 못했는데 전체적인 흐름과 Servlet 3.0에 대해서도 알게 되어 나름 알차게 들었습니다. 그리고 튜닝을 주업무로 하시는 이상민님의 설명이었기에 추천해 주시는 부분에 대해서 성능에 대한 걱정을 따로 하지 않아도 되는 점이 좋았습니다. 다만 중간에 Comet에 대한 언급을 하시면서 Client의 연결없이도 클라이언트에 데이터를 푸쉬한다는 얘기를 하셨었는데 정확히 의도하신 의미는 몰라도 Comet도 최초의 요청을 통해 Connection 연결은 해야 되는 것으로 알고 있어서 이부분은 잘못 전달된 내용이 아닌가 싶습니다.






Java용 구글 앱 엔진과 스프링 - 박성철
Track 4의 세번째 세션입니다.
스프링의 전략은 "Next evolution for java is to better integrate the techs"로 표현할 수 있으며 생산성을 향상하고 VMware로 인한 클라우딩 컴퓨팅에 대한 것입니다. 그동안 엔터프라이즈 자바의 고민은 생산성에 대해서는 관심이 없고 소위 얼마나 뽀대가 나는가 얼마나 팔리느냐에만 관심이 있었습니다. 여기에 두가지 솔루션이 있는데 오랫동안 지원해왔고 자바의 자산은 그대로 이용하면서 동적언어가 좋은 경우에는 Groovy + Grails, 그리고 동적언어에는 별로 관심이 없으면 SpringRoo입니다.

사용자 삽입 이미지

SrpingRoo
SpringRoo의 생산성 전략의 특징은 수분안에 기본 애플리케이션의 뼈대를 생성하는 극적인 생상선 향상과 RoR로부터 취한 관례 우선(CoC), 프로젝트를 자동으로 구성하고 보일러플레이트문제를 해결함으로써 반복작업을 제거하고 스프링을 기반으로 하고 있다는데에 있습니다. 스프링소스와 구글앱진의 기술적 제휴는 5월 19일에 발표를 하고 Spring Tools Suite에서 구글앱엔진을 지원하고 SpringRoo(and Grails)와 Google Web Toolkit를 연동했으면 Spring Insigt와 Google Spped Tracer로 모니터링을 하는 것이었습니다. 이 기술적 제휴는 구글은 앱엔진을 Biz영역에까지 사용하고 싶었고 VMware는 Open PaaS 영역까 진입하고 싶은 데서 이루어졌습니다.

SpringRoo는 단순작업을 최소화하고 양방향(Round Trip)인 코드생성기이며 엔티티 중심의 DDD스타일1(정확히 DDD라고 할 수는 없지만 DDD에 기반을 두고 있습니다)로 레이어가 단순화 된 기본 아키텍쳐를 두고 있습니다. 특징으로는 SpringRoo는 컴파일단계에서만 관여하기 때문에 실제 소스에 SpringRoo에 대한 코드는 없어서 실행시의 자원을 차지하거나 하는 성능에 대한 문제가 전혀 없으며 Spring, JPA, Log4j, Maven, AspectJ등 일반적인 자바기술을 이용하고 있으면 자유롭게 제거가 가능하고 오픈소스입니다.

SpringRoo는 아주 쉬운 사용법을 가지고 있고 Shell기반으로 동작을 하면 Hint라는 명령어를 입력하면 현재 단계에서 무엇을 해야하는지 가이드 해주면 탭! 탭! 탭!을 통해서 명령어를 쉽게 완성할 수 있습니다. 프로그래밍은 디자인입니다. 개발자는 설계를 하는 사람이지 단순히 코드를 찍어내는 작업이 아니기 때문에 단순작업은 컴퓨터가 하게 하는 것입니다. 프로젝트 구성/생성, 빌드스크립트 생성/관리, 의존성라이브러리 관리는 자동화하고 개발자는 설계에만 집중하도록 하자는 것입니다. 이번에 추가된 것이 GWT이고 GWT를 사용하면 기본적인 CRUD가 되는 GWT앱을 간단히 생성할 수 있습니다.

SpringRoo의 아키텍쳐는 엔티티 계층은 JPA, AspectJ를 사용하고 웹계층은 Spring MVC, Tiles를 사용하며 서비스계층은 선택사항으로 제공하고 있습니다. 레파지토리는 선택사항이기 때문에 DAO계층은 게저했으면 차후 1.1.0버전에서 RIA에 대한 지원을 할 예정입니다.

GAE/J
GAE는 클라우드 컴퓨팅 서비스로 구글이 내부에서 사용하던 인프라와 관리기술을 공개적으로 열어준 플래폼 서비스(PaaS)로 처음에는 파이썬을 지원하고 이어서 Java를 지원하였습니다. 클라우드라는 것은 갑자기 튀어나온 개념은 아니고 이전부터 얘기가 있었던 것으로 LISP를 만든 John McCarthy는 "Compuation may someday be organized as a public utility."(전산자원은 언젠가 공공재가 될 것이다.)라고 했으며 John Gage의 "The Network is the Computer"라는 말은 유명합니다.

클라우드의 핵심 특징은 기민성과 확장성이고 적은 돈으로 위기에 대응할 수 있으며 보안에 강하며 장비(지역)에 독립적입니다. 또한 유지보수가 안정적이고 전문가가 대신 관리해주기 때문에 신뢰할 수 있습니다. 클라우스 서비스의 구성요소는 클라이언트와 애플리케이션( SaaS)가 필요하고 플랫폼은 Paas로 제공되며 구글 앱엔진이 이 역할을 하고 있습니다. 하부구조는 IaaS(Infrastruct as a Service)로 제공됩니다.

GAE/J의 특성으로는 구글애플리케이션과 동일한 인프라와 관리기술을 그대로 이용할 수 있으며 수평 확장성2이 좋으며 JDK 6, JPA, JDO, Servelt등의 고유 자바기술을 이용할 수 있고 서비스 기반이며 구글의 빅테이블을 이용할 수 있다는 점입니다. 빅테이블은 스키마가 없는 데이터 저장소로 GAE에서는 매우 중요하지만 GAE를 사용할 때 가장 어려워 하는 부분중 하나입니다. 기본적인 사용은 무료로 할 수 있다는 장점도 있습니다. 개발환경은 이클립스에 구글 플러그인을 설치만 하면 되며 로컬 개발서버에서 테스트를 할 수 있고 GWT와 통합되어 있습니다.

개인적으로는 세션의 제목이 직관적으로 정해지지 않은게 아닐까 하는 생각이 들었습니다. 올해 공개된 스프링소스와 구글의 협력에 대한 부분인데 구체적으로 보자면 5월 Google I/O에서 벤알렉스가 SpringRoo와 Google App Engine의 연동에 대해서 보여준 내용이 주된 내용이라고 할 수 있는데 대부분의 내용이 Spring과 SpringRoo에 대한 설명이었고 제목을 보고 제가 기대했던 Google App Engine에 대한 내용은 다소 적었었습니다. 이 부분은 마지막 부분에 GAE와의 연동 시연을 준비하신 것 같았는데 시간조절의 실패로 연동 시연이 이루어지지 않아 더 그렇게 느껴졌을 수도 있습니다.






스프링 3.0을 활용한 RESTful 웹서비스 개발 - 백기선, 김성윤
제가 속해있는 봄싹의 세션으로 스프링 3.0에서 추가된 RESTful에 대한 세션이었습니다. 주로 라이브 코딩 및 코딩데모를 위주로 진행이 되었기 때문에 내용상 정리할 수 있는 부분은 많지 않아 간략하게 정리합니다.

요청 URL을 클래스등에 매핑시키는 @RequestMapping을 put, delete등의 메서드등을 받을 때 사용할 수 있으면 @PathVariable은 요청 URL의 아이디 같은 부분을 변수에 할당할 수 있습니다. 현재의 웹브라우저들에서는 대부분 Get/Post밖에 사용할 수 없기 때문에 스프링의 폼태그에서 method라는 이름의 히든필드에 PUT등의 원하는 메서드를 적어서 REST를 사용할 수 있습니다.

발표하는 백기선님 & 김성윤님발표하는 백기선님 & 김성윤님

ContentsNegotiatingViewResolver
ViewResolver는 View를 찾아내는 역할을 하는데 미디어타입을 이용해서 어떤 뷰를 찾아야 할지를 결정하는 기능을 합니다. 이때 미디어 타입의 결정은
URL 확장자 -> format 파라미터 -> Access 헤더정보 -> defaultContentType
순으로 결정하게 됩니다. 뷰의 후보를 선정할때는 viewResolvers를 사용하지 않으면 서블릿 콘텍스트에 등록된 모든 ViewResolver을 사용해서 뷰 후보를 선정하고 ViewResolvers를 사용하면 모든 ViewResolvers가 돌려주는 뷰를 후보 목록에 추가합니다. 이때 defaultView속성을 설정한 뷰는 무조건 후보목록에 추가가 됩니다.

RestTemplate
RestTemplate는 Spring 3.0 M2에서 추가된 것으로 스프링의 Template 시리즈(JDBCTemplate, JmsTemplate 등)와 비슷한 형태를 가지고 있습니다. RESTful스타일의 URL을 지원하고 HTTP access를 단순화 해줍니다. 현재 베이직 인증만 지원하고 있고 OAuth인증은 Spring 3.1 M1에서 지원예정에 있는 상태입니다.

발표자료 링크

시연귀신이 유독 괴롭혔던 세션이었습니다. 대부분의 세션내용을 라이브코딩으로 준비하였는데 백기선님의 발표에서는 Java파일을 수정하여도 WAS의 재기동없이 적용할수 있게 하여 개발속도를 빠르게 할 수 있는 JRebel이 수시로 제대로 동작하지 않았으며 김성윤님의 발표에서는 심지어 IntelliJ가 얼어버리는 사태까지 발생한 관계로 진행자체가 깔끔하게 흘러가지는 않았지만 라이브코딩은 일반적인 발표와는 또다른 매력이 있기 때문에 전달해야 할 부분은 어느정도 전달되었던 듯 합니다. 깔끔히 시연이 되었다면 더 명확했겠지만 시연귀신은 어쩔수 없는 일이라고 생각하고 있습니다.(팔이 안으로 굽는 것일지도요 ㅡㅡ;;)




덧) 작년 이맘때만 해도 세미나는 항상 혼자 왔다갔다 했는데 언젠가부터는 세미나를 가면 아는 사람이 많아졌습니다. 이번에도 의도한 것은 아니지만 전 세션을 개인적으로 아시는 분들의 세션을 들었습니다. 개인적으로 알다보니 세션 주제에 관심이 가게 된 것인지 관심갖고 있는 주제의 사람들과 친분을 갖게 된것인지 명확하지는 않습니다. 이전에는 항상 3자의 입장이었던데 비해 요즘은 지인에 대한 후기를 쓰게되는 일이 최근에 많아지게 되어 후기를 적다보면 항상 100% 만족할 수는 없기 때문에 안좋은 얘기를 하는 부분에 대해서는 전에 비해 신경이 많이 쓰이는 것은 사실입니다.
 좋은 말만 하는 것은 서로에게 그다지 도움되는 일도 아니고 평소에도 많이 배우고 있는 그분들은 그정도의 비판(?)은 충분히 받아들일 수 있는 분들이라고 생각하기 때문에 신경은 쓰이지만 왠만하면 느낀대로 쓰려고 하고 있습니다. 전 시크하거든요...


덧2) 나름 테크니컬 블로그를 지향하지만(수준을 떠나서) 요즘은 후기전문이 되어가는 것인가 하는 느낌이 없잖아 있기는 하지만 그렇다고 쓰던 후기를 안쓸수는 없으니 더 기술적인 부분에 대해서 노력해야겠습니다.
  1. 보통은 로직을 서비스레이어에 두어 소스가 중복되고 서비스레이어가 복잡해 지는데 이 로직을 도메인 객체에 두자는 것이 DDD입니다. [Back]
  2. 하드웨어를 업그래이드 하는 것이 아닌 추가로 서버를 추가하여 확장하는 것을 의미하며 한계가 매우 높습니다. [Back]
2010/07/14 03:04 2010/07/14 03:04