톰캣 8 소개

아파치 톰캣(Apache Tomcat) 8 버전이 곧 베타에서 정식 버전으로 발표될 예정인데 스프링 프레임웍 팀에서 웨비나를 하길래 오늘 방금 전 자정부터 1시까지 그걸 봤다. 동영상 리플레이 및 발표 자료는 1-2주 후에 https://www.youtube.com/springsourcedev에 올린다고 한다. 아래 웨비나 내용 및 공부한 내용을 정리해본다. 예제 출처는 github.com/swilliams-pivotal/s2gx-tomcat다.

사실 톰캣 8 자체보다는 톰캣이 구현하는 자바 EE의 기능 소개 성격이 더 강한 웨비나였는데 아무튼 일단 톰캣 8은 다음 내용으로 요약할 수 있다.

  • 서블릿 3.1
  • JSP 2.3
  • EL(Expression Language) 3.0
  • 웹소켓 1.0
  • 기타 자바 EE 7 기능

서블릿 3.1

서블릿 3.0부터 HTTP 입출력에 큰 기능이 하나 추가됐는데 바로 “차단되지 않는 입출력(non-blocking IO)”이다. 그전까지는 말하자면 웹브라우저 하나에서 웹페이지를 다운로드(또는 업로드)할 때 페이지 로딩이 끝날 때까지 다른 아무 것도 할 수가 없었다. 하지만 이제는 입출력을 비동기적으로 처리할 수 있어서 서버가 다른 작업을 하면서 입출력을 처리할 수 있다. (다른 말로 또는 반대로 말하자면 입출력을 처리하면서 동시에 다른 작업을 할 수 있다. 이것이 가능한 것은 입출력을 별도의 자바 스레드를 생성해 처리하기 때문이다.)

다음 예제 코드를 보자. 아주 단순한 예제로서 실용성은 전혀 없는데 개념은 잘 드러나 있다.

  1.     @Override
  2.     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
  3.         // 1. Start Async
  4.         final AsyncContext asyncContext = req.startAsync();
  5.  
  6.         // 2. Add Write Listener - to say Hello
  7.         ServletOutputStream outputStream = resp.getOutputStream();
  8.         WriteListener listener = new WriteListener() {
  9.             @Override
  10.             public void onWritePossible() throws IOException {
  11.                 // 3. Write to output stream 
  12.                 ServletOutputStream output = asyncContext.getResponse().getOutputStream();
  13.                 if (output.isReady()) {
  14.                     output.print("Hello World!");
  15.                 }
  16.  
  17.                 // 4. Call complete, to signal we are done
  18.                 asyncContext.complete();
  19.             }
  20.  
  21.             @Override
  22.             public void onError(Throwable throwable) {
  23.                 throwable.printStackTrace(System.err);
  24.                 asyncContext.complete();
  25.             }
  26.         };
  27.         outputStream.setWriteListener(listener);
  28.     }

서블릿의 doGet 메서드를 보인 것인데 4행에서 HttpServletRequest#startAsync 메서드를 호출하여 비동기 처리를 준비하고 WriteListener 인터페이스를 구현하여 비동기적으로 "Hello World!"를 출력하고 있다. 비동기적이므로 27행에 이후에 뭔가 다른 코드가 있다면 해당 코드가 실행되면서 동시에 "Hello World!"를 클라이언트로 출력하는 작업은 그 작업대로 실행될 것이다.

이 글은 톰캣 8 소개 글이므로 차단되지 않는 입출력은 여기까지만 알아보기로 한다.

JSP 2.3

JSP 2.3은 “maintenance release”로서 톰캣 8에서 그 전 버전과 별 차이가 없다고 한다.

Expression Language 3.0

EL 3.0은 이전 버전과 많이 달라졌지만 하위 호환성이 있다고 한다. 이전 버전과 달리 ELProcessor라는 클래스를 단순 빈(bean) 방식으로 선언하여 사용할 수 있으므로 JSP가 아닌 임의의 자바에서도 EL을 사용할 수 있게 됐다.

    // EL을 사용할 수 있는 API를 제공하는 ELProcessor 생성
    ELProcessor processor = new ELProcessor();
 
    // 간단한 데이터 등록 및 EL 실행
    processor.defineBean("person", this.person);
    System.out.println(processor.eval("person.name"));
 
    // EL 3.0에서는 셋, 리스트, 맵을 쉽게 선언할 수 있다.
    Set set = (Set) processor.eval("{1, 2, 3, 3, 2, 1}");
    System.out.println("Set -> " + set);
 
    List list = (List) processor.eval("[1, 2, 3, 3, 2, 1]");
    System.out.println("List -> " + list);
 
    Map<String,Integer> map = (Map<String, Integer>) processor.eval("{'one': 1, 'two': 2, 'three': 3}");
    System.out.println("Map -> " + map);

EL 3.0은 위의 예시 외에도 덧셈 연산자(+)로 문자열 연결하기, map/reduce 등 다양한 기능이 추가됐다.

웹소켓 1.0

톰캣 7에서도 웹소켓 API를 지원했으나 톰캣 8 및 7.0.43부터 새로운 API로 웹소켓이 구현됐다고 한다. 또한 톰캣 7에서는 차단되는(blocking) 방식이었으나 웹소켓 1.0에서는 거의 비차단식으로 제공된다.

@ServerEndpoint("/websockets/events/annotation")
public class EventsAnnotationEndpoint {
 
    // called when connection is opened, use blocking api to send a response message
    @OnOpen
    public void onOpen(Session session) {
        try {
            session.getBasicRemote().sendText("Welcome!");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    // called on close, we do nothing.
    @OnClose
    public void onClose() {
        // Clean up resources here
    }
 
    // called when a full message is received, we echo back to client using blocking api
    @OnMessage
    public void onMessage(Session session, String message) {
        try {
            session.getBasicRemote().sendText("Echo [" + message + "]");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
}

톰캣 자체의 변화

  • 이전에는 자원(파일)을 찾기 위한 방식으로 Aliases, VirtualLoader, VirtualDirContext, JAR 파일 등 여러가지를 server.xml에 설정할 수 있었는데 8 버전부터 간단하게 일원화했다고 한다. 자세한 사항은 https://tomcat.apache.org/tomcat-8.0-doc/config/resources.html을 참고한다.
  • rewrite 밸브가 추가됐다. 설정 구문에 대한 설명을 대충 보니 아파치 http 서버의 mod_rewrite와 거의 같은 것 같다. 이제 톰캣 만으로도 복잡한 URL 고쳐쓰기가 가능한 것이다.
  • 자바 7 이상이 필요하다
  • 비차단식 입출력을 지원하기 위해 NIO 커넥터가 기본 설정이 됐다. 이전처럼 BIO나 APR/네이티브 입출력도 계속 지원한다.
  • DB 연결 풀링에는 그전까지 DBCP를 사용했는데 이제 DBCP 2가 기본이 됐다. 아파치 DBCP에서는 명확히 DBCP 2가 발표되지 않은 상태인데 아마도 톰캣에서 먼저 구현하고 있는 게 아닐까 생각된다.

일정

톰캣 8의 일정은 다음과 같다고 한다.

  • 자바 EE 7에서 구현할 기능은 모두 완료된 상태
  • 8.0.3 베타에 대해 2월 9일 투표 예정
  • 상용으로 사용하기에는 아직 이른 베타 버전인 상태

이상으로 웨비나 및 내가 간단히 찾아본 내용 정리를 마치기로 한다. 베타 버전 상태므로 실전에서 사용하기에는 부족하다고 하지만 톰캣이 원래 개발자들이 손쉽게 사용할 수 있는 웹 서블릿 컨테이너였으므로 개발단에서 톰캣 8을 사용하는 데 별 문제는 없을 것 같다. 모바일 환경이나 HTML 5가 중요한 흐름인 시대가 됐으므로 서블릿/JSP나 웹소켓 등의 최신 기술을 남보다 먼저 사용해보는 것이 여러 모로 유익하지 않을까 생각된다.

톰캣 8 소개”에 대한 의견

  1. 방문해주셔서 감사합니다. 좋은 글이라니 더 감사드리고요. 스크랩 OK입니다~ ^^

의견 있으시면 냉큼 작성해주세요~