자바 기반인 tomcat 은 아파치 진영의 또 다른 산물이다. JSDK(servlet)의 설치 없이 tomcat만의 설치로 servlet과 jsp를 바로 사용할 수 가 있다.
Tomcat은 JSP 환경을 지원하는 Servlet Container 이다. Servlet Container는 사용자를 대신하여 Servlet 을 관리하고 Invoke 하는 실시간 쉘(Runtime Shell)이다.
이는 기존의 Servlet 을 지원하는 Jserv 와는 다르며 Tomcat 과 대표적인 차이는 JSDK 가 필요없다는 것이며 Jserv는 Servlet 2.0 까지만을 지원하나 Tomcat은 Servlet 2.2와 JSP 1.1을 지원한다는 것이다.
Servlet Container은 크게 세가지로 분류되며 다음과 같다.
1.Stand-alone Servlet Container : Tomcat 자체가 자바 기반의 Web Server로 사용된다. 이는 Tomcat 에서 Default mode 이다.
2.In-process Servlet Container : Web Server Plugin과 Java Container를 조합한 구현 형태이며 Apache 등의 Web Server 에 추가하여 사용하는 형태이다. 하나의 프로세스내에 멀티 쓰레드를 구현한 형태이며 이는 좋은 퍼포먼스(performance)를 가지나 하나의 프로세스내에서 각 서블릿이 멀티 쓰레드화되어 구현되므로 쓰레드의 동시 실행 개수가 제한된다( limited Scalability). 구현 형태는 Web Server Plugin이 JVM을 Web Server의 주소(Address) 영역내에 open 한 후 그 주소 영역내에서 JVM 이 실행될 수 있도록 하게 한다. 서블릿을 실행하려는 어떤 요청이 오면 Plugin은 제어권을 받아 Java Container에게 건네준다.
3.Out-of-process Servlet Container : In-process Servlet Container 와 비슷하나 JVM 은 Web Server 주소영역의 외부에서 실행된다. Web Server Plugin 과 Java Container(JVM) 은 IPC 메커니즘(대개 TCP/IP 소켓)을 사용하여 통신한다. 서블릿을 실행하려는 어떤 요청이 들어오면 plugin 은 제어권을 받아 IPC 메카니즘을 사용하여 Java Container(JVM) 에게 건네준다. Out-of-process 에서는 요청에 대한 응답시간(response time) 이 In-process보다는 좋지 않지만 scalability 나 stability 등에서 좋다.
기타 servlet 의 경우 매번 컴파일할때마다 아파치의 재기동없이 바로 실행 결과를 볼 수 있어 개발자에게는 더없이 즐겁다. (하지만 대체로 재컴파일된 서블릿 은 바로 로딩이 안되고 브라우져를 죽였다가 다시 시작하면 되는데 이게 왜이런지 아시는 분은 메일이나 제 홈에 글좀 남겨주세요)
기타 이 문서는 Tomcat에 대한 최소한의 문서이므로 Tomcat 에 대한 다른 문서들도 참조하기 바란다. 가장 적절한 참고 사이트는 Jakarta 의 홈페이지이며 기타 http://kldp.org 에서 "Tomcat" 으로 검색을 하여 김상수님의 Tip문서를 찾거나 http://webdox.co.kr 에서 김민식님과 김세곤님이 함께 쓴 문서를 찾아 참조하기 바란다.
설치에 앞서 필자의 테스트환경은 다음과 같다
여기에서 소개하는 설치는 Apache Plugin 형태이다.
1. 설치전에 아파치와의 연동을 위해 아파치는 DSO 로 컴파일되어 있어야 한다.
Apache Configure 및 컴파일 예
[root@nogadax src]$ ./configure --prefix=/usr/local/apache \
--enable-module=most \
--enable-shared=max
[root@nogadax src]$ make
[root@nogadax src]$ make install
2. JDK1.1.x 버젼 이상이 설치되어 있어야 한다.
3. http://jakarta.apache.org/downloads/binindex.html 에서 이미 컴파일된 바이너리 패키지(jakarta-tomcat.tar.gz)를 다운받고 mod_jserv.so 를 다운받는다.
4. 적당한 디렉토리에 바이너리 패키지의 압축을 풀면 설치 완료이다.
1. 다운받은 mod_jserv.so 를 (아파치 디렉토리의) apache/libexec 디렉토리에 복사한다.
2. TOMCAT_HOME과 JAVA_HOME 환경변수를 설정한다.
만약 tomcat 의 경로가 /usr/local/jakarta-tomcat 이면 /etc/profile 등의 파일에 다음처럼 설정한다.
export TOMCAT_HOME=/usr/local/jakarta-tomcat
JAVA_HOME 또한 마찬가지로 jdk의 경로가 /usr/local/jdk1.2.2 이면 다음과 같다.
export JAVA_HOME=/usr/local/jdk1.2.2
그런 후 설정 화일을 실행하여 변수를 메모리로 올리면 된다.
(예 : [root@nogadax local]$ . /etc/profile )
3. tomcat 디렉토리의 conf 디렉토리에 존재하는tomcat-apache.conf 를 아래처럼 아파치 디렉토리 밑의 conf 디렉토리내의 httpd.conf 파일의 제일 마지막에 추가하면 된다.(참고로 이 화일의 내용은 tomcat 에 의해 실행될때마다 자동으로 변경되어 설정된다.)
Include /usr/local/jakarta-tomcat/conf/tomcat-apache.conf
먼저 tomcat 을 실행한 후에 아파치를 실행한다.
1. tomcat 실행은 tomcat 의 bin 디렉토리의 "tomcat.sh start" 나 "startup.sh" 를 실행한다.
2. 아파치를 실행한다.(apachectl start)
1. tomcat을 종료한다. 실행때와 마찬가지로 tomcat 의 bin 디렉토리의 "tomcat.sh stop" 나 "shutdown.sh" 를 실행한다.
2. 아파치를 종료한다.(apachectl stop)
테스트는 URL 이 http://210.110.144.235 일때에 다음과 같다.
http://210.110.144.235/examples/servlets
http://210.110.144.235/examples/jsp
Servlet 의 컴파일을 위해 tomcat 디렉토리 밑의 lib 디렉토리의 "servlet.jar" 을 CLASSPATH 에 등록하면 된다. (이외에 다른 방법이 있으면 저의 홈이나 메일로 보내주시면 고맙겠습니다.)
예 : export CLASSPATH=$CLASSPATH:/usr/local/jakarta-tomcat/lib/servlet.jar
그런 후 servlet 프로그램들을 컴파일하면 된다.
tomcat에서server.xml 은 중요한 화일이다. 화일내의 중요한 설정요소로는 Server,Logger,ContextManager ,ContextInterceptor와 RequestInterceptor,Connector,Context 등이 있으며 그중에 기초적으로 알아야 할 부분은 Context 가 아닌가 싶다. 필자가 모든 요소에 대해 알고 있지는 않은 상태이며 최소한의 부분만 짐작하고 있을 뿐이다.
Server.xml 에서 Context 설정부분은 Web Application(Servlet이나 JSP)이 위치할 장소를 설정하며 WEB 상의 PATH(경로)를 설정한다. 기타 재컴파일된 서블릿을 자동으로 재로딩한다.
참고로 Context(webapps,work)의 base 디렉토리는 ContextManager 의 Home이며 TOMCAT_HOME 하고는 의미가 다르다. 만약 ContextManager 의 Home 이 /usr/local/jakarta-tomcat 이면 샘플용의 Web Application 이 포함된 webapps 의 절대경로는 /usr/local/jakarata-tomcat/webapps 이다. 실제로 샘플용의 web application(servlets,JSPs) 가 들어 있는 경로는 /usr/local/jakarta-tomcat/webapps/examples/WEB-INF/classes 이다.
기타 work 디렉토리는 Tomcat 실행중 중간 형태의 파일이 위치하며(예를 들어 컴파일된 JSP 파일) 이 디렉토리가 Tomcat 실행중에 삭제된다면 JSP 가 실행이 되지 않는다.
아래는 화일은 모든 내용은 아니지만 다음의 부분만 보자.
<Context path="/examples" docBase="webapps/examples" debug="0" reloadable="true">
</Context>
<Context path="/pgsql" docBase="webapps/pgsql" debug="0" reloadable="true">
</Context>
<Context path="/websql" docBase="webapps/websql" debug="0" reloadable="false">
</Context>
Context는 이전의 jserv 에서 리포지터리 역활을 하는 ZONE 과 같은 것으로 보인다.
제일 위의 examples 는 샘플용의 예제가 있으며 tomcat 의 설치 후 web 상에서 바로 실행할 수가 있다. 샘플용의 예제는 examples/WEB-INF/classes 에 있다.
샘플용인 examples 의 Hello 서블릿을 실행하기 위한 위의 WEB 상의 주소는 http://your_host_address/examples/servlet/Hello 이다.
web상에서 examples를 /examples/servlet 로 사용하는 이유는 다음과 같다.
tomcat 이 시작되면 conf 디렉토리의 server.xml 을 참조한 후 tomcat-apache.conf를 자동 설정한다. 그 중에 Context 에 설정된 PATH 를 참조하여 자동으로 적절하게 설정한다. 바로 이파일(tomcat-apache.conf)에 examples 를 들어가는 경로가 examples/servlet 로 설정된다.(여기에 대한 사항은 tomcat 실행후 이 파일을 참조하기 바란다.) tomcat-apache.conf 가 설정된 후에 아파치를 기동하면 아파치는 Tomcat에 의해 자동 설정된 tomcat-apache.conf 를 참조하여 실행된다.
reloadable="true"는 Auto-reloadable 이며 false이면 웹 어플리케이션의 Auto-reloadable 이 되지 않는다.
기타 pgsql 과 websql 은 필자가 테스트를 위해 만든 것이다. 이 두개의 디렉토리는 webapps 디렉토리에 생성하였고 각각의 디렉토리에는 또 다른 하위 디렉토리를 만들어야 한다.(WEB-INF/classes) 다음은 그 예이다.
webapps/pgsql/WEB-INF/classes
webapps/websql/WEB-INF/classes
최종 디렉토리인 classes 에 서블릿 클래스들이 들어가면 되며 tomcat 실행후 tomcat 디렉토리의 "tomcat-apache.conf" 를 보라
다음은 pgsql을 브라우져에서 사용하는 URL 예이다.
http://210.110.144.235/pgsql/servlet/example_servlet
위의 example_servlet 는 서블릿(example_servlet.class)이며 "pgsql/WEB-INF/classes" 이 있다.
Tomcat 3.1 에 postgreSQL의 JDBC 연동은 의외로 간단하다. 환경변수 CLASSPATH 에 등록하기만 하면 된다. 그러면 Tomcat 실행시 자동으로 읽어서 JDBC 를 로딩한다.
CLASSPATH 설정 예
export CLASSPATH=$CLASSPATH:/usr/local/pgsql7.0.2/jdbc/postgresql.jar
Tomcat 에서의 한글처리는 Apache-Jserv 와 동일하다.
아래는 개략적인 소스입니다.
..............
..............
public void doGet(HttpServletRequest req , HttpServletResponse res)
throws ServletException,IOException
{
.......
.......
PrintWriter out;
res.setContentType("text/html;charset=euc-kr");
out=new PrintWriter(new OutputStreamWriter(
res.getOutputStream(),"KSC5601"));
.......
.......
}
.....
.....
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException,IOException
{
res.setContentType("text/html;charset=euc-kr");
PrintWriter out=new PrintWriter(new OutputStreamWriter(
res.getOutputStream(),"KSC5601"));
....
String id=ksc(req.getParameter("id"));
String name=ksc(req.getParameter("name"));
String juso=ksc(req.getParameter("juso"));
String tel=ksc(req.getParameter("tel"));
String memo=ksc(req.getParameter("memo"));
....
....
}
.....
.....
public String ksc(String kscstr)
throws UnsupportedEncodingException
{
if(kscstr==null) return null;
return new String(kscstr.getBytes("8859_1"),"KSC5601");
} // ksc() 함수는 문자를 KSC5601로 변환한다.
............................................................
또한 포스트그레스7.0.2에 한글을 삽입하기전에 KSC5601로 변환하여야 한다. 그렇지 않으면 포스트그레스에 들어간 한글은 바로 깨진다. 기타 다른 버젼은 아마 비슷할 거로 추측되며 아직 테스트는 못해 보았다.
아래처럼 문자를 ksc()함수로 ksc5601 로 변환한 후에 포스트그레스에 insert 하면 된다.
String id=ksc(req.getParameter("id"));
String name=ksc(req.getParameter("name"));
String juso=ksc(req.getParameter("juso"));
String tel=ksc(req.getParameter("tel"));
String memo=ksc(req.getParameter("memo"));