아파치 톰캣(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)"이다. 그전까지는 말하자면 웹브라우저 하나에서 웹페이지를 다운로드(또는 업로드)할 때 페이지 로딩이 끝날 때까지 다른 아무 것도 할 수가 없었다. 하지만 이제는 입출력을 비동기적으로 처리할 수 있어서 서버가 다른 작업을 하면서 입출력을 처리할 수 있다. (다른 말로 또는 반대로 말하자면 입출력을 처리하면서 동시에 다른 작업을 할 수 있다. 이것이 가능한 것은 입출력을 별도의 자바 스레드를 생성해 처리하기 때문이다.)
다음 예제 코드를 보자. 아주 단순한 예제로서 실용성은 전혀 없는데 개념은 잘 드러나 있다.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. Start Async
final AsyncContext asyncContext = req.startAsync();
// 2. Add Write Listener - to say Hello
ServletOutputStream outputStream = resp.getOutputStream();
WriteListener listener = new WriteListener() {
@Override
public void onWritePossible() throws IOException {
// 3. Write to output stream
ServletOutputStream output = asyncContext.getResponse().getOutputStream();
if (output.isReady()) {
output.print("Hello World!");
}
// 4. Call complete, to signal we are done
asyncContext.complete();
}
@Override
public void onError(Throwable throwable) {
throwable.printStackTrace(System.err);
asyncContext.complete();
}
};
outputStream.setWriteListener(listener);
}
서블릿의 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나 웹소켓 등의 최신 기술을 남보다 먼저 사용해보는 것이 여러 모로 유익하지 않을까 생각된다.