Getting Started Xdoclet

Toggle Space Navigation Tree
Space Map

Xdoclet 사용하기

Summary : 웹 애플리케이션의 구조가 점점 복잡해지면서 하나의 웹 애플리케이션을 개발하기 위하여 관리해야하는 Descriptor파일들(web.xml, taglib files, ejb-jar.xml등)이 점차 많아지고 있다. 또한 개발되는 애플리케이션에서 다른 프레임워크을 추가하는 경우라면 이 수는 더욱 증가하게 된다. 스트럿츠를 이용하기 위해서도 struts-config.xml을 따로 관리해주어야 한다. Xdoclet을 이용하여 수 많은 Descriptor파일과 소스파일 사이의 동시성을 유지하도록하는 방법에 대하여 살펴본다.

예제 실행 방법

스트럿츠의 세부 항목을 살펴보기에 앞서 이 장의 Xdoclet예제를 먼저 실행해보는 것이 이 장을 이해하는데 많은 도움이 될 것이다. 따라서 이 장의 예제를 실행하는 방법에 대하여 살펴보도록 하겠다. 3장 예제의 디렉토리 구조를 살펴보면 다음과 같다.

3장 예제를 실행하기 위한 과정을 살펴보면 다음과 같다. Tomcat, ANT의 설치에 관한 자세한 내용은 부록 1을 참조하기 바란다. 다음 설명은Tomcat, ANT가 설치되어 있다는 가정하에 설명을 진행하도록 하겠다.

3장의 Xdoclet예제를 빌드하는 방법은 간단하다. 이 장에서 개발한 Xdoclet예제는 servlet, taglib, struts 3가지 설정파일을 자동생성하는 방법에 대하여 살펴보았다. 따라서 3가지 예제를 각각 실행해 보기 위하여 빌드 또한 3가지 방법으로 할 수 있도록 구현하였다. 따라서 빌드하는 과정을 3가지 방법으로 살펴보도록 하겠다.

Servlet - web.xml

  • 1) web.xml파일을 자동 생성하기 위한 예제를 보기 위해서는 프롬프트에서 chapter3로 이동한 다음 'ant servlet' 명령어를 실행하여 servlet 예제를 빌드한다. 빌드하기 전에는 web.xml파일이 없었지만 빌드 후 web.xml이 자동 생성된 것을 확인할 수 있다.
  • 2) 빌드가 정상적으로 진행되면 chapter3 디렉토리 하위에 dist라는 디렉토리가 생성되면서 chapter3.war파일이 생성된다.
  • 3) 만약 시스템 환경 변수에 CATALINA_HOME 이 설정되어 있다면 CATALINA_HOME/webapps 디렉토리에 chapter3.war파일이 자동으로 디플로이 된다. 시스템 환경 변수에 CATALINA_HOME이 설정되어 있지 않다면 chapter3/dist디렉토리 아래의 chapter1.war파일을 CATALINA_HOME/webapps 에 복사한다.
  • 4) Tomcat서버를 시작한 후 다음 URL로 접근하여 예제를 테스트할 수 있다.

http://localhost:8080/chapter3/HelloWorldServlet

http://localhost:8080/chapter3/HelloWorld

http://localhost:8080/chapter3/hi.HelloWorld

  • 5) 자세한 테스트 방법 및 설명은 2.3절의 본문을 참조하기 바란다.

Taglib - *.tld

  • 1) 커스텀 태그 설정파일인 tld파일을 자동 생성하기 위한 예제를 보기 위해서는 프롬프트에서 chapter3로 이동한 다음 "ant taglib" 명령어를 실행하여 taglib 예제를 빌드한다. 빌드하기 전에는 mytaglib.tld파일이 없었지만 빌드 후 mytaglib.tld이 자동 생성된 것을 확인할 수 있다.
  • 2) 빌드가 정상적으로 진행되면 chapter3 디렉토리 하위에 dist라는 디렉토리가 생성되면서 chapter3.war파일이 생성된다.
  • 3) 만약 시스템 환경 변수에 CATALINA_HOME 이 설정되어 있다면 CATALINA_HOME/webapps 디렉토리에 chapter3.war파일이 자동으로 디플로이 된다. 시스템 환경 변수에 CATALINA_HOME이 설정되어 있지 않다면 chapter3/dist디렉토리 아래의 chapter3.war파일을 CATALINA_HOME/webapps 에 복사한다.
  • 4) Tomcat서버를 시작한 다음 http://localhost:8080/chapter3/helloworld.jsp URL로 접근하여 taglib 예제를 테스트할 수 있다. 자세한 테스트 방법 및 설명은 2.3절의 본문을 참조하기 바란다.

Struts - struts-config.xml

  • 1) 스트럿츠 설정파일인 struts-config.xml을 자동 생성하기 위한 예제를 보기 위해서는 프롬프트에서 chapter3로 이동한 다음 "ant struts" 명령어를 실행하여 struts 예제를 빌드한다. 빌드하기 전에는 struts-config.xml파일이 없었지만 빌드 후 struts-config.xml이 자동 생성된 것을 확인할 수 있다.
  • 2) 빌드가 정상적으로 진행되면 chapter3 디렉토리 하위에 dist라는 디렉토리가 생성되면서 chapter3.war파일이 생성된다.
  • 3) 만약 시스템 환경 변수에 CATALINA_HOME 이 설정되어 있다면 CATALINA_HOME/webapps 디렉토리에 chapter3.war파일이 자동으로 디플로이 된다. 시스템 환경 변수에 CATALINA_HOME이 설정되어 있지 않다면 chapter3/dist디렉토리 아래의 chapter3.war파일을 CATALINA_HOME/webapps 에 복사한다.
  • 4) Tomcat서버를 시작한 다음 http://localhost:8080/chapter3/user_write.jsp URL로 접근하여 struts 예제를 테스트할 수 있다. 자세한 테스트 방법 및 설명은 2.3절의 본문을 참조하기 바란다.

기타

  • 1) 웹 애플리케이션 기본 디렉토리 구조로 생성된 예제는 chapter3/build 디렉토리에 생성된다. 따라서 [그림 3-1]의 디렉토리 구조가 생소한 독자들은 빌드를 실행한 다음 chapter3/build 디렉토리를 참조하면 쉽게 이해할 수 있다.
  • 2) 각각의 개발 방법으로 새로 빌드하면 이전에 빌드한 디렉토리 내용은 삭제된다. 따라서 servlet 예제 소스만을 보고 싶다면 "ant servlet""" 빌드한 다음 chapter3/build 디렉토리를 보면 된다. taglib, struts 예제 또한 동일한 방법으로 빌드 및 테스트할 수 있다.

빌드시 주의할 점과 궁금한 점.

  • 1) 처음 빌드할 때는 상관없지만 한번 빌드한 예제의 소스를 수정한 다음 다시 빌드하고자 할 때는 Tomcat서버를 멈춘 상태에서 해야한다. 이유는 Tomcat서버가 시작된 상태일 경우 이전에 디플로이했던 디렉토리가 삭제되지 않는 문제가 발생해 빌드가 실패하는 경우가 발생하기 때문이다. 따라서 빌드는 항상 Tomcat서버가 멈춘 상태에서 실시해야 한다.
  • 2) [그림 3-1]을 보면 WEB-INF디렉토리와 컴파일된 class파일이 없는 것을 볼 수 있다. 또한 독자들이 첨부된 CD의 예제소스를 보면 web.xml, struts-config.xml, mytaglib.tld 파일들이 보이지 않는다. 이 파일들은 ANT로 빌드하면 자동생성되기 때문에 빌드를 실행한 다음 chapter3/build/WEB-INF 디렉토리에서 찾을 수 있다. 따라서 예제 소스에 보면 web.xml, struts-config.xml, mytaglib 파일들이 없다고 의아해할 필요는 없다.
  • 3) 모델 2나 스트럿츠를 기반으로한 애플리케이션을 개발하기 위해서는 기존의 모델1에 추가적으로 설정해야하는 정보가 있다. 그러나 이 장의 예제는 ANT로 빌드시 자동적으로 설정되기 때문에 추가적인 설정이 필요없다.
  • 4) 예제 소스를 독자들이 수정해보고 싶다면 src디렉토리의 예제 소스나 JSP파일을 수정한 다음 새로 빌드하면 자동 컴파일 및 war로 압축되기 때문에 독자들이 수정한 예제를 테스트해볼 수 있다.

*2. Ant와 Xdoclet을 이용한 개발 방법*

웹 애플리케이션의 구조가 점점 복잡해지면서 하나의 웹 애플리케이션을 개발하기 위하여 관리해야하는
Descriptor파일들(web.xml, taglib files, ejb-jar.xml등)이 점차 많아지고 있다.
또한 개발되는 애플리케이션에서 다른 프레임워크을 추가하는 경우라면 이 수는 더욱 증가하게 된다. 스트럿츠를
이용하기 위해서도 struts-config.xml을 따로 관리해주어야 한다.

웹 애플리케이션의 규모가
커지면 커질수록 이 같이 관리해야하는 Descriptor파일은 무수히 많아진다. 따라서 개발되고 있는 소스가
수정되면 Descriptor파일과 소스파일간의 동시성(synchronization)을 일치시키기 위하여 많은
시간을 할애해야한다.

특히 EJB를 기반으로 개발하는 웹 애플리케이션의 경우 관리해야하는
Descriptor파일의 수는 2배이상 증가하게 된다. EJB같은 경우 EJB를 지원하는 벤더에 따라
Descriptor파일이 달라지기 때문에 이에 따른 동시성을 유지하는 것 또한 상당히 많은 시간을 요구한다. 또한
EJB를 기반으로 개발할 경우 하나의 컴포넌트를 개발하기 위하여 7개 이상의 많은 파일을 추가로 개발해주어야한다.
EJB에 새로운 인터페이스가 추가될 경우 더불어 변경해주어야 하는 파일의 수 또한 많다. EJB를 기반으로 개발을
해본 개발자들이라면 Descriptor파일과 소스파일사이의 동시성을 유지하는데 얼마나 많은 시간이 소요되는지 느낄
것이다.

Xdoclet은 점점 더 복잡해지고, 수 많은 Descriptor파일과 소스파일
사이의 동시성을 유지하도록 하는 코드 생성 엔진이다. Xdoclet은 자바로 웹 애플리케이션을 개발할 경우
Attribute Oriented Programming(이하 AOP, Aspect Oriented
Programming이 아니다.)이 가능하도록 한다. 자바 소스코드에서 JavaDoc 태그를 이용하여
JavaDoc을 생성해본 개발해본 개발자라면 Xdoclet의 AOP개발 방식에 대하여 쉽게 이해할 수 있다.
JavaDoc을 생성하는 방식을 보면 자바소스의 주석 내에 JavaDoc 태그를 이용하여 JavaDoc문서를
자동으로 생성할 수 있다. Xdoclet 또한 각 컴포넌트별로 정의된 태그를 자바 소스에 사용함으로 인해 자바소스
및 Descriptor파일을 자동으로 생성할 수 있는 방식이다. 따라서 자바 소스코드가 수정될 경우
Descriptor파일을 수정할 필요가 없어진다. 소스코드 하나만 관리하면 되기 때문에 상당한 개발시간의
단축효과를 볼 수 있으며, 자바소스와 Descriptor파일의 동시성 또한 유지할 수 있다.

Xdoclet 사이트에서는 Xdoclet을 사용할 경우 다음과 같은 이득을 얻을 수 있다고 주장한다.

  • 1. 소스코드가 변경될 때마다 Descriptor파일을 걱정할 필요없다. Descriptor파일은 소스가
    변경될 때마다 계속해서 새로 생성된다.
  • 2. 특히 EJB를 기반으로 개발할 경우 하나의 컴포넌트를 개발하기 위하여 7개 또는 그 이상의 파일을
    개발해야 한다. 그러나 Xdoclet을 사용할 경우 하나의 소스코드만 생성하면 된다. 나머지 소스파일 및
    Descriptor파일은 Xdoclet이 자동생성해준다.
  • 3. Xdoclet을 이용할 경우 개발시간을 상당히 단축시킬 수 있다. 개발자들은 단지 비지니스 로직에만
    전념할 수 있다.
    글로만 Xdoclet의 놀라운 점을 설명하는데는 한계가 있다. Xdoclet을 이용하여 web.xml,
    struts-config.xml을 자동생성하는 예제를 보면 Xdoclet의 매력에 흠뻑 빠질 것이다. 아직
    Xdoclet이 뭔지 모르겠다고 조급해하지마라. 계속되는 예제를 통해 Xdoclet에 대하여 이해할 수 있을
    것이다.

Xdoclet의 진정한 장점은 EJB를 개발할 때 발휘된다. 그러나 스트럿츠 프레임워크도 많은
소스파일과 struts-config.xml의 동시성을 유지해야하는 만큼 Xdoclet의 장점을 피부로 느낄 수
있을 것이다. 이 책의 모든 예제는 Xdoclet 기반위에서 개발할 것이다. 스트럿츠 프레임워크를 이용하여
개발해본 개발자들이라면 자바 소스파일과 struts-config.xml의 동시성을 유지하는 것이 얼마나 어려운지
알 것이다. 특히 여러명의 개발자들이 프로젝트를 진행할 때 동시성을 유지하기란 더 어렵다. Xdoclet을
이용하여 비지니스 로직을 개발하는 것 이외에 발생했던 많은 시간을 단축할 수 있기 바란다.

*2.1 Xdoclet 설치*

Xdoclet으로 web.xml, ejb-jar.xml, struts-config.xml등의
Descriptor파일을 자동으로 생성하기 위해서는 먼저 ANT가 설치되어 있어야 한다. ANT의 설치 및
사용법은 부록을 참조하기 바란다.

Xdoclet은
http://xdoclet.sourceforge.net에서 오픈소스로 개발되고 있기 때문에 무료로 사용이
가능하다. 2003년 8월 현재 최신 버전은 1.2.0 베타3상태이다. 이 책에서는 1.2.0 베타3
버전을 이용하여 개발하도록 하겠다. Xdoclet을 설치하는 과정은 다음과 같다.

에서 Xdoclet 1.2.0 베타3 버전을 다운받는다.

  • 2. 다운받은 파일을 개발자들이 원하는 위치에 압축을 푼다.
  • 3. Xdoclet을 사용하기 위하여 필요한 모든 Jar파일들은 Xdoclet압축을 푼 디렉토리
    아래의 lib에 위치해 있다. 모든 Jar파일들을 웹 애플리케이션의 라이브러리를 관리하는 디렉토리에
    복사한다.
    이상으로 Xdoclet을 사용할 모든 준비가 완료되었다. 다음은 ANT를 이용하여 자바 소스에 생성한 각
    컴포넌트별 태그를 이용하여 Descriptor파일을 자동적으로 생성하면 된다.

이 책의
모든 예제는 이미 Xdoclet이 설치되어 있는 상태이기 때문에 추가적으로 설치할 jar파일은 없다.
Xdoclet관련 패키지는 각 장 예제의 lib디렉토리 하위의 xdoclet 디렉토리(1,2장은
lib/main/xdoclet)에 위치해 있다. 만약 Xdoclet을 이용하는 새로운 애플리케이션을 개발할
경우 위 설치과정에 따라 Xdoclet을 설치하면 된다.

*2.2 Xdoclet 예제*

Xdoclet예제는 보여주기 위하여 먼저 서블릿예제를 먼저 보도록 하자. 서블릿을 생성한 다음 웹
애플리케이션에서 사용하기 위하여 web.xml에 매핑해주어야 한다. 스트럿츠 또한 서블릿을 사용하고
있으며, web.xml에서 설정이 필요하기 때문에 서블릿예제를 먼저 살펴보는 좋다고 생각한다. 다음은
Xdoclet의 다양한 예제를 살펴보기 위하여 커스텀 태그 예제를 살펴보도록 하겠다. 하나의 커스텀 태그를
만들기 위해서는 tld파일을 생성할 필요가 있다. 개발을 진행하는 중 커스텀 태그에 애트리뷰트가 하나
추가될 때마다 tld파일을 수정해 주어야 하는 불편함이 있다. Xdoclet을 이용하여 이 같은 단계를
줄일 수 있는 방법에 대하여 살펴보도록 하겠다.

마지막 예제로 스트럿츠 프레임워크를 이용하여 웹
애플리케이션을 Xdoclet을 이용하여 개발하는 과정에 대하여 살펴보도록 하겠다. 스트럿츠 프레임워크의
경우에 하나의 요청을 처리하기 위하여 Action, Form, Exception 정보들을
struts-config.xml에서 관리해야 한다. Xdoclet을 이용하여 수많은 클래스들과
struts-config.xml의 동시성을 유지하는 방법에 대하여 알아보겠다.

*2.2.1 서블릿 예제*

자바로 웹 애플리케이션을 개발해본 개발자들이라면 web.xml이 웹 애플리케이션의 배치
Descriptor파일이라는 것을 알 것이다. 서블릿을 하나 추가한 다음 웹 애플리케이션에서
사용하기 위해서 web.xml에서 매핑을 추가한다. 그러나 Xdoclet을 이용하면 web.xml에
추가하지 않아도 된다. 개발자는 web.xml에 추가하고자하는 정보를 단지 서블릿에서 정해진 태그를
이용하여 추가하면 된다.

package net.javajigi.chapter3.servlet;

import java.io.IOException;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @web.servlet name="HelloWorldServlet" 
 * 				display-name="HelloWorld Servlet" 
 * 
 * @web.servlet-init-param 	name="name" 
 * 							value="${hello.servlet.name}"
 * 
 * @web.servlet-mapping url-pattern="/HelloWorld/*"
 * @web.servlet-mapping url-pattern="*.HelloWorld"
 * @web.servlet-mapping url-pattern="/HelloWorldServlet"
 */
public class HelloWorldServlet extends HttpServlet {

	protected void doGet(
		HttpServletRequest request,
		HttpServletResponse response)
		throws ServletException, IOException {
		process(request, response);
	}

	protected void doPost(
		HttpServletRequest request,
		HttpServletResponse response)
		throws ServletException, IOException {
		process(request, response);
	}

	protected void process(
		HttpServletRequest request,
		HttpServletResponse response)
		throws ServletException, IOException {
		ServletConfig config = this.getServletConfig();
		String name = config.getInitParameter("name");

		response.setContentType("text/html");
		java.io.PrintWriter out = response.getWriter();
		out.println("<html>");
		out.println("<head>");
		out.println("<title>HelloWorld Servlet</title>");
		out.println("</head>");
		out.println("<body>");
		out.println("<h1>Hih2. " + name + ". Hello Worldh2.</h1>");
		out.println("</body>");
		out.println("</html>");
		out.close();
	}
}

[예제 3-1]HelloWorldServlet.java

[예제 3-1]
Xdoclet의 webdoclet ANT Task를 실행시키면 [예제 3-2]와 같은
web.xml이 생성된다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" 	"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app >
	...
	<distributable/>
	<servlet>
		<servlet-name>HelloWorldServlet</servlet-name>
		<display-name>HelloWorld Servlet</display-name>
		<servlet-class> 
			net.javajigi.chapter3.servlet.HelloWorldServlet</servlet-class>
		<init-param>
			<param-name>name</param-name>
			<param-value>JavaJiGi</param-value>
		</init-param>
	</servlet>
	...
	<servlet-mapping>
		<servlet-name>HelloWorldServlet</servlet-name>
		<url-pattern>/HelloWorld/*</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>HelloWorldServlet</servlet-name>
		<url-pattern>*.HelloWorld</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>HelloWorldServlet</servlet-name>
		<url-pattern>/HelloWorldServlet</url-pattern>
	</servlet-mapping>
	...
</web-app>

[예제 3-2]web.xml

다음은 [예제 3-2]와 같은 결과가 어떻게
생성되는지 단계적으로 자세하게 살펴보도록 하겠다. [예제 3-2]와 같은 결과를 얻기 위해서는 먼저
서블릿을 작성할 때 Xdoclet태그를 작성해주어야 한다. Xdoclet태그를 이용하여 작성된
서블릿을 ANT로 빌드하여 web.xml을 자동으로 생성할 수 있다.

*2.2.1.1 단계 1 : 서블릿 엘리먼트를 정의하는 방법*

Xdoclet을 이용하여 web.xml에 서블릿을 자동으로 매핑하기 위해서는 먼저
JavaDoc 태그를 작성하듯이 클래스 레벨에서 다음과 같이 작성해야 한다.

/**
 * @web.servlet name="HelloWorldServlet" 
 * 	 	display-name="HelloWorld Servlet" 
 ...
 */

public class HelloWorldServlet extends HttpServlet {

위와 같이 작성된 태그에 의하여 생성되는 web.xml은 다음과 같다.

<servlet>
      <servlet-name>HelloWorldServlet</servlet-name>
      <display-name>HelloWorld Servlet</display-name>
      <servlet-class>net.javajigi.chapter3.servlet.HelloWorldServlet</servlet-class>
...
</servlet>

생성된 web.xml을 보고 '>servlet-class/<는 어떻게 알 수 있을까?'라고
의문을 가지는 개발자들이 있을 것이다. Xdoclet도 JavaDoc API를 생성하는
과정과 같은 방법으로 생성되기 때문에 소스코드의 패키지 이름을 포함한 클래스 정보를 얻을 수
있다. JavaDoc API를 생성할 때 자바 소스코드의 패키지명 및 클래스이름과 같은
정보를 같이 제공하지 않아도 자동적으로 생성되는 과정을 보면 쉽게 이해할 수 있을
것이다.

*2.2.1.2 단계 2 : 서블릿 초기 인자를 정의하는 방법*

서블릿을 개발하다보면 서블릿에 초기 인자를 전달해야 하는 경우가 발생한다. web.xml에서
초기 인자를 전달할 수 있도록 작성하는 방법은 다음과 같다.

  • @web.servlet-init-param name="name"

  • value="$

    Unknown macro: {hello.servlet.name}

    "

    위 태그는
    web.xml에서 >init-param/<태그를 생성한다.

    <init-param>
             <param-name>name</param-name>
             <param-value>JavaJiGi</param-value>
    </init-param>
    

    생성된 web.xml을 보면 web.servlet-init-param에서 작성된 내용이
    >init-param/<에 반영된 것을 확인할 수 있다. 궁금한 부분은
    >param-value/<의 값이 Xdoclet 태그에서는
    $

    와 같이 작성되었는데 web.xml에서는
    JavaJiGi로 바뀌어 생성된 것이다. 이는 ANT를 이용하여 빌드하면서
    hello.servlet.name이름을 가지는 변수의 값으로 대체하라는 것이다. ANT에서
    정의한 hello.servlet.name는 다음과 같다.

#HelloWorldServlet에서 참조하고 있음. 원하는 값으로 수정할 수
있다.

hello.servlet.name=JavaJiGi

*2.2.1.3 단계 3 : 서블릿 매핑을 정의하는 방법*

마지막으로 추가된 서블릿을 사용하기 위해서는 서블릿 매핑이 필요하다. 서블릿 매핑에 대해서는
굳이 설명하지 않아도 알 것이라 생각한다. Xdoclet태그를 이용하여 서블릿 매핑을 하는
방법은 다음과 같다.

  • @web.servlet-mapping
    url-pattern="/HelloWorld/*"
  • @web.servlet-mapping
    url-pattern="*.HelloWorld"

  • @web.servlet-mapping
    url-pattern="/HelloWorldServlet"

위 태그는
web.xml에서 >servlet-mapping/<태그를 자동적으로 생성한다.

<servlet-mapping>
      <servlet-name>HelloWorldServlet</servlet-name>
      <url-pattern>/HelloWorld/*</url-pattern>
   </servlet-mapping>
   <servlet-mapping>
      <servlet-name>HelloWorldServlet</servlet-name>
      <url-pattern>*.HelloWorld</url-pattern>
   </servlet-mapping>
   <servlet-mapping>
      <servlet-name>HelloWorldServlet</servlet-name>
      <url-pattern>/HelloWorldServlet</url-pattern>
</servlet-mapping>

web.xml의 서블릿 매핑 정보는 web.servlet-mapping태그를 이용하여
자동생성한다. web.servlet-mapping태그를 이용하여 URL 패턴만 설정해주면
자동으로 서블릿 이름을 찾아 >servlet-mapping/<태그를 완성한다.

2.2.1.4 단계 4 : ANT 빌드를 통하여 web.xml생성하기

단계 3까지의 과정으로 서블릿을 작성했다면 마지막 과정을 ANT를 이용하여 빌드함으로서
web.xml을 생성하는 과정이 남아 있다. web.xml을 생성하기 위하여 Xdoclet의
webdoclet Task를 이용해야 한다.(Task에 대한 자세한 내용은 부록을 참조하기
바란다.) Ant 빌드 파일의 >taskdef/<태그에 다음과 같이 설정함으로서
webdoclet Task를 이용할 수 있다.

<taskdef name="webdoclet"
               classname="xdoclet.modules.web.WebDocletTask" 
               classpathref="xdoclet.class.path"
 />

Xdoclet의 Task들은 ANT에서 이미 정의 되어 있는 Task가 아니기 때문에 위와
같이 정의함으로서 webdoclet Task를 사용할 수 있다.
xdoclet.modules.web.WebDocletTask는 앞에서 설치한 Xdoclet의
lib내의 jar파일에 있기 때문에 Xdoclet의 jar파일을 참조할 수 있도록
클래스패스를 정의하고 있다.

ANT에서 webdoclet을 이용하여 web.xml을
생성하는 Target을 보면 다음과 같다.

<target name="generateDD" depends="init">
      <taskdef name="webdoclet"
               classname="xdoclet.modules.web.WebDocletTask" 
               classpathref="xdoclet.class.path"
      />

      <webdoclet destdir="${build.dir}">
         <fileset dir="${src.dir}">
            <include name="**/*Servlet.java" /> 
<include name="**/*Filter.java" />
         </fileset>

         <deploymentdescriptor servletspec="2.3" 
         			  destdir="${build.dir}/WEB-INF" >
         </deploymentdescriptor>
      </webdoclet>
</target>

web.xml은 최종적으로 >webdoclet/<태그의
>deploymentdescriptor/<태그에 의하여 자동적으로 생성된다.
생성되는 web.xml의 내용은 소스디렉토리내의 Servlet으로로 끝나는 소스코드의 내용에
따라 결정되게 되는 것이다. 이 절의 서블릿예제에서 작성된 서블릿은
HelloWorldServlet하나이기 때문에 HelloWorldServlet의 내용만이
web.xml로 자동생성된다.

web.xml이 생성되는 과정을 확인해
보자. 책에서 제공하는 chapter3디렉토리를 보면 WEB-INF디렉토리가 없는 것을 볼
수 있다. 앞에서 war파일을 생성한 것처럼 "ant servlet"" 하면
chapter3.war파일이 생성되면서 자동 디플로이된다. 디플로이된
chapter3.war파일에는 web.xml이 생성되어 있는 것을 확인할 수 있다.
chapter3/build디렉토리를 보아도 WEB-INF가 생성되어 있으며,
WEB-INF디렉토리 아래에 web.xml이 자동 생성되어 있는 것을 확인할 수 있다. 자동
생성된 web.xml의 내용은 [예제 3-2]와 같다는 것을 확인할 수 있다. Tomcat
서버를 시작하여 다음 URL로 접근해보면 web.xml이 제대로 생성되었는지를 테스트할 수
있다.

http://localhost:8080/chapter3/HelloWorldServlet

http://localhost:8080/chapter3/HelloWorld

http://localhost:8080/chapter3/hi.HelloWorld

위 세개의 URL모두 다음과 같은 결과를 얻을 수 있을 것이다.

[그림 3-10] HelloWorldServlet을 실행한 결과

web.xml을 생성하기 위한 Xdoclet태그에 대해 더 자세한 정보는
http://xdoclet.sourceforge.net/tags/web-tags.html

를 참조하기 바란다.

*2.2.2 커스텀 태그 예제*

커스텀 태그 하나를 생성하기 위해서는 커스텀 태그 클래스를 먼저 작성해야 한다. 그 다음 생성된 커스텀 태그 정보를 가지는 tld파일을 생성해야 한다. tld파일에서 가장 많이 수정되는 부분은 커스텀 태그에 애트리뷰트가 추가, 수정, 삭제될 때이다. 개발하고 있는 웹 애플리케이션에서 많은 수의 커스텀 태그를 개발한다면 이 또한 상당한 작업 시간으로 요한다. 개발자사이에 tld파일의 동시성을 유지하는 것 또한 쉽지 않다. 따라서 커스텀 태그 tld파일을 Xdoclet을 이용하여 생성하는 과정에 대하여 살펴보도록 하겠다.

package net.javajigi.chapter3.taglib;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.TagSupport;

/**
 * @jsp.tag name="helloWorld"
 */
public class HelloWorldTag extends TagSupport {
	private String name = null;

	public int doStartTag() throws JspException {
		try {
			JspWriter out = pageContext.getOut();

			out.println("Hih2. " + name + ". Hello Worldh2.");
		} catch (IOException e) {
			throw new JspException(e.getMessage());
		}

		return SKIP_BODY;
	}

	/**
	 * @jsp.attribute	required="true" 
	 *                  rtexprvalue="true"
	 *                  description="User Name"
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param string 
	 */
	public void setName(String name) {
		this.name = name;
	}

}

[예제 3-3]HelloWorldTag.java

[예제 3-3]의 커스텀 태그
예제를 Xdoclet을 이용하여 생성된 tld파일은 다음과 같다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib 	PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN" 	"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
	<tlib-version>1.0</tlib-version>
	<jsp-version>1.2</jsp-version>
	<short-name> helloworld </short-name>
	<tag>
		<name>helloWorld</name>
		<tag-class>net.javajigi.chapter3.taglib.HelloWorldTag</tag-class>
		<attribute>
			<name>name</name>
			<required>true</required>
			<rtexprvalue>true</rtexprvalue>
			<description>User Name</description>
		</attribute>
	</tag>
</taglib>

[예제 3-4] mytaglib.tld

[예제 3-3]을 ANT를 이용하여 빌드하면
[예제 3-4]와 같은 tld파일을 자동으로 생성할 수 있다. 위의 커스텀 태그 예제도
Xdoclet을 이용하여 tld파일을 자동적으로 생성하는 과정에 대하여 살펴보도록 하겠다.

*2.2.2.1 단계 1 : 태그 이름을 정의하는 방법*

커스텀 태그 이름을 정의하기 위해서는 클래스 레벨의 Xdoclet 태그인 jsp.tag를
사용하면 된다.

/**
 * @jsp.tag name="helloWorld"
 */
public class HelloWorldTag extends TagSupport {

jsp.tag Xdoclet태그에 의하여 작성된 tld파일은 다음과 같다.

<name>helloWorld</name>
<tag-class>net.javajigi.chapter3.taglib.HelloWorldTag</tag-class>

생성된 tld파일을 보면 서블릿 예제에서 본 바와 같이 태그 이름만 정의하면 태그 클래스에
대한 패키지, 클래스 이름등의 정보는 자동적으로 생성되는 것을 확인할 수 있다.

*2.2.2.2 단계 2 : 태그 애트리뷰트를 정의하는 방법*

태그를 생성할 때 가장 자주 변경되는 부분이 애트리뷰트이다. 애트리뷰트는 메써드 레벨의
Xdoclet 태그를 이용하여 자동적으로 생성할 수 있다. 커스텀 태그의 애트리뷰트를
추가하는 과정은 다음과 같다.

/**
	 * @jsp.attribute	required="true" 
	 *                  rtexprvalue="true"
	 *                  description="User Name"
	 */
	public String getName() {
		return name;
	}

jsp.attribute 태그의 내용을 보면 tld파일의 애트리뷰트를 추가할 때 필요한 모든
항목이 있음을 볼 수 있다. 애트리뷰트 이름은 자동적으로 생성된다. 위 소스코드에 의하여
생성된 tld파일은 다음과 같다.

<attribute>
         <name>name</name>
         <required>true</required>
         <rtexprvalue>true</rtexprvalue>
         <description>User Name</description>
</attribute>

HelloWorldTag에 name 애트리뷰트 이외에 다른 애트리뷰트를 추가한 다음
getter 메써드에 위 예제 소스와 같이 Xdoclet 태그를 추가한 다음 새로 빌드해주면
새로운 애트리뷰트의 추가는 끝난다.

*2.2.2.3 단계 3 : ANT빌드를 통하여 web.xml, tld파일 생성하기*

Xdoclet태그를 통하여 작성된 소스코드는 서블릿과 같이 ANT를 이용하여 최종 빌드함으로서
tld파일을 생성할 수 있다. 자동적으로 생성된 tld파일을 web.xml에 추가해주고
싶다면 ANT의 Target 내용을 다음과 같이 작성하면 된다.

<target name="generateDD" depends="compile">
      <taskdef name="webdoclet"
               classname="xdoclet.modules.web.WebDocletTask" 
               classpathref="xdoclet.class.path"
      />

      <webdoclet destdir="${build.dir}">
         <fileset dir="${src.dir}">
            <include name="**/*Tag.java" />           
         </fileset>

 <!-- 
 web.xml을 생성하는 역할을 담당하며, 
 web.xml에 새로 생성되는 tld파일을 추가한다.
 -->
         <deploymentdescriptor servletspec="2.3" 
         			destdir="${build.webinf.dir}" >  
                <taglib uri="http://www.javajigi.net/mytaglib"
                    location="/WEB-INF/tlds/mytaglib.tld"
                />         						        						
         </deploymentdescriptor>
         
 <!-- 
 tld파일을 생성하는 부분이다.
 -->         
         <jsptaglib 	jspversion="1.2" 
         		destdir="${build.webinf.dir}/tlds"

		shortname="helloworld" 
		filename="mytaglib.tld"/>
      </webdoclet>
 </target>

tld파일을 자동적으로 생성하기 위하여 ANT의 Target을 작성할 때 두가지 사항을
고려해야 한다. 첫번째는 생성된 tld파일을 web.xml에 추가하기 위한
부분이고(>deploymentdescriptor/<태그), 두번째는 커스텀 태그 소소를
이용하여 tld파일을 생성하는 것이다(>jsptaglib/<태그).
>deploymentdescriptor/<태그에 의하여 생성된 web.xml의 내용은 다음과
같다.

<taglib>
      <taglib-uri>http://www.javajigi.net/mytaglib</taglib-uri>
<taglib-location>/WEB-INF/tlds/mytaglib.tld</taglib-location>
</taglib>

지금까지 작성한 예제를 테스트해보기 위하여 "ant taglib"" 실행하여
chapter3.war를 빌드한다. ANT로 빌드한 다음
chapter3/WEB-INF/tlds를 보면 mytaglib.tld파일이 생성되어 있는
것을 확인할 수 있다. Tomcat서버를 시작한 다음
http://localhost:8080/chapter3/helloworld.jsp
테스트해보면 [그림 3-10]과 같은 결과를 얻을 수 있다. helloworld.jsp예제
소스는 다음과 같다.

<%@page contentType="text/html; charset=euc-kr" %>
<%@ taglib uri="http://www.javajigi.net/mytaglib" prefix="mytag"%>
<html>
<head>
	<title>HelloWorld Tag</title>
</head>
<body>
<h1>
	<mytag:helloWorld name="JavaJiGi"/>
</h1>
</body> 
</html>

[예제 3-5] mytag를 사용하고 있는 helloworld.jsp

커스텀 태그의 tld파일을 생성하기 위한 Xdoclet태그에 대해 더 자세한 정보는
http://xdoclet.sourceforge.net/tags/web-tags.html#@jsp.tag
(0..1) 를 참조하기 바란다.

*2.2.3 스트럿츠 예제*

지금까지 서블릿과 커스텀 태그 소스코드에 Xdoclet태그를 추가하여 web.xml과 tld파일을 자동으로 생성하는 방법에 대하여 배웠다. 스트럿츠를 기반으로하는 웹 애플리케이션에서도 서블릿과 커스텀 태그를 작성하는 경우가 많기 때문에 지금까지 살펴본 위 예제는 계속해서 사용된다.

스트럿츠를 기반으로하는 애플리케이션은 struts-config.xml을 생성하기 위하여 지금까지 살펴본 예제들보다 훨씬 더 많은 클래스들이 관여한다. struts-config.xml이 포함하고 있는 정보들을 보면 Action, ActionForm, Exception, Plugin,Controller등 수 많은 정보들을 포함하고 있다. 이 절에서는 Xdoclet을 이용하여 struts-config.xml을 자동으로 생성하는 방법에 주안점을 두고 있기 때문에 이 중 가장 많이 사용되는 Action, ActionForm만을 살펴보도록 하겠다. 나머지 항목에 대해서는 4장부터 다루는 실전예제들에서 다루도록 하겠다. struts-config.xml이 자동으로 생성되는 과정을 보면 Xdoclet의 필요성을 다시 한번 느낄 수 있을 것이다.

package net.javajigi.chapter3.struts.form;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;

/** 
 * XDoclet definition:
 * @struts:form name="userForm"
 */
public class UserForm extends ActionForm {
	private String password = null;
	private String userId = null;
	private String email = null;
	private String name = null;

	public ActionErrors validate(
		ActionMapping mapping,
		HttpServletRequest request) {
		
		return null;
	}

	public void reset(ActionMapping mapping, HttpServletRequest request) {
		password = null;
		userId = null;
		email = null;
		name = null;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getUserId() {
		return userId;
	}

	public void setUserId(String userId) {
		this.userId = userId;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getName() {
		return name;
	}

	public void setName(String string) {
		name = string;
	}
}

[예제 3-6] UserForm.java

package net.javajigi.chapter3.struts.action;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.javajigi.chapter3.struts.form.UserForm;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

/**
 * @struts.action
 *      name="userForm"
 *      path="/userInfo"
 *      input="/user_write.jsp"
 *      scope="request"
 *      validate="true"
 *
 * @struts.action-forward
 *      name="userinfo"
 *      path="/user_info.jsp"
 */
public class UserAction extends Action{
	public ActionForward execute(
		ActionMapping mapping,
		ActionForm form,
		HttpServletRequest request,
		HttpServletResponse response)
		throws Exception {
			
		request.setAttribute("user", (UserForm)form);
				
		return mapping.findForward("userinfo");
	}
}

[예제 3-7] UserAction.java

[예제 3-6], [예제 3-7]
스트럿츠 프레임워크를 기반으로 웹 애플리케이션을 개발할 때 가장 많은 수와 많은 시간을 할애하는
Form과 Action클래스이다. Xdoclet예제를 위하여 1장의 사용자 관리 프로젝트의 일부분을
발췌하였다. [예제 3-6], [예제 3-7]에서 Xdoclet태그를 사용한 부분은 볼드처리된
부분이다. 이 두 예제에 의하여 생성된 struts-config.xml은 다음과 같다.

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN" "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<struts-config>

  <!-- ========== Data Sources Definitions =================================== -->
  <!--
    Define your Struts data sources in a file called struts-data-sources.xml and place
    it in your merge directory.
  -->

  <!-- ========== Form Bean Definitions =================================== -->
  <form-beans>
    <form-bean
      name="userForm"
      type="net.javajigi.chapter3.struts.form.UserForm"
    />

    <!--
         If you have non XDoclet forms, define them in a file called struts-forms.xml and
         place it in your merge directory.
    -->
  </form-beans>

  <!-- ========== Global Exceptions Definitions =================================== -->
  <!--
    Define your exceptions in a file called global-exceptions.xml and place
    it in your merge directory.
  -->

  <!-- ========== Global Forward Definitions =================================== -->
  <!--
    Define your forwards in a file called global-forwards.xml and place
    it in your merge directory.
  -->

  <!-- ========== Action Mapping Definitions =================================== -->
   <action-mappings>
    <action
      path="/userInfo"
      type="net.javajigi.chapter3.struts.action.UserAction"
      name="userForm"
      scope="request"
      input="/user_write.jsp"
      unknown="false"
      validate="true"
    >
      <forward
        name="userinfo"
        path="/user_info.jsp"
        redirect="false"
      />
    </action>

    <!-- If you have non XDoclet actions, define them in a file called struts-actions.xml and place it in your merge directory. -->
  </action-mappings>

   <!-- Define your Struts controller in a file called struts-controller.xml and place it in your merge directory. -->

   <!-- Define your Struts message-resources in a file called struts-message-resources.xml and place it in your merge directory. -->

   <!-- Define your Struts plugins in a file called struts-plugins.xml and place it in your merge directory. -->

</struts-config>

[예제 3-8]struts-config.xml

[예제 3-6]와 [예제
3-7]에서 작성한 Xdoclet태그 내용이 그대로 struts-config.xml에 생성된 것을
확인할 수 있다. 개발자들은 struts-config.xml의 생성에 대해서 신경쓸 필요없이, 현재
작업하고 있는 Form과 Action소스코드에서 struts-config.xml에 추가하고 싶은
내용을 추가해주면 된다. 소스코드에 있는 모든 내용이 struts-config.xml에 자동으로
추가되기 때문에 동시성을 유지하기 위하여 노력할 필요도 없다. 앞의 예제와 같이
struts-config.xml이 생성되는 과정에 대해서도 단계별로 살펴보도록 하겠다.

*2.2.3.1 단계 1 : Form 이름을 정의하는 방법*

스트럿츠의 Form은 DynaActionForm을 상속하는 Form이 아닐 경우에는
Form이름만 정의해주면 된다(DynaActionForm에 대해서는 5장에서 다루도록
하겠다.). Form이름을 정의하는 Xdoclet태그는 다음 예제와 같이 클래스 레벨에서
정의할 수 있다.

/** 
 * XDoclet definition:
 * @struts:form name="userForm"
 */
public class UserForm extends ActionForm {

위 소스코드에 의하여 생성되는 struts-config.xml의 태그는 >form-bean/<태그이다.

<form-bean
      name="userForm"
      type="net.javajigi.chapter3.struts.form.UserForm"
/>

struts:form Xdoclet태그에 의하여 >form-bean/<태그가 생성되는 내용에
대해서 더 이상 설명하지 않아도 이해할 수 있을 것이다. 계속되는 예제를 통해 보는 바와
같이 간단한 Xdoclet태그 하나를 추가함으로서 여러줄의 Desriptor를 자동으로
생성하는 것을 볼 수 있다.

*2.2.3.2 단계 2 : Action 정보를 정의하는 방법*

하나의 Action을 정의하는 것은 Form처럼 간단하지 않다.
struts-config.xml내의 >action/<태그를 정의하기 위해서도 무수히 많은
애트리뷰트가 존재하듯이 Xdoclet을 이용하여 Action정보를 정의하는 것도 같은
구조이다.

/**
 * @struts.action
 *      name="userForm"
 *      path="/userInfo"
 *      input="/user_write.jsp"
 *      scope="request"
 *      validate="true"
 *
 * @struts.action-forward
 *      name="userinfo"
 *      path="/user_info.jsp"
 */
public class UserAction extends Action{

Action클래스에서 정의해야할 Action클래스의 정보는 두가지로 나뉜다. 첫번째는
Action클래스의 경로, 입력폼, 스코프등이며, 두번째는 요청을 완료한 다음 이동할 경로를
정의해야 한다. 위 예제 소스에 의하여 자동 생성된 struts-config.xml의
>action/<태그는 다음과 같다.

<action-mappings>
<action
  path="/userInfo"
  type="net.javajigi.chapter3.struts.action.UserAction"
  name="userForm"
  scope="request"
  input="/user_write.jsp"
  unknown="false"
  validate="true"
>
  <forward name="userinfo" path="/user_info.jsp" redirect="false"/>
</action>

UserAction클래스에서 작성된 Xdoclet의 Action정보가 그대로
>action/<태그내에 담겨 있다. 스트럿츠 프레임워크에 Xdoclet을 처음 적용할 때는
기존 방식보다 개발 속도가 더 빠르다는 것을 느끼지 못할 것이다. 그러나 Form,
Action클래스의 내용을 수정하여 struts-config.xml을 수정해야 하는 경우가
자주 발생하면 할수록 Xdoclet의 위력을 실감할 수 있을 것이다.

*2.2.3.3 단계 3: ANT 빌드를 통하여 struts-config.xml 생성하기*

앞에서 작성한 UserForm, UserAction을 이용하여
struts-config.xml을 자동으로 생성하기 위한 ANT의 Target을 작성해보자.

<target name="generateDD" depends="compile">
  <taskdef name="webdoclet"
		   classname="xdoclet.modules.web.WebDocletTask" 
		   classpathref="xdoclet.class.path"
  />

  <webdoclet 
	 destdir="${build.dir}"
	 mergedir="${merge.dir}"
  > 
	 <fileset dir="${src.dir}">
		<include name="**/*Filter.java" /> 
		<include name="**/*Action.java" />
		<include name="**/*Form.java" />          
	 </fileset>

	 <deploymentdescriptor servletspec="2.3" 
			          destdir="${build.webinf.dir}" >  
	 </deploymentdescriptor>
	 
	 <strutsconfigxml destdir="${build.webinf.dir}"/>
  </webdoclet>
</target>

Target의 내용은 앞에서 살펴본 두 예제와 별반 다르지 않다. 특이할만한 부분은 ANT의
merge기능을 이용하기 위하여 mergedir을 사용한 것과
struts-config.xml을 생성하기 위하여 webdoclet Task의
>strutsconfigxml/<태그를 사용했다는 것이다. merge 기능에 대해서는 다음
단계에서 살펴보도록 하겠다.

*2.2.3.4 단계 4 : 스트럿츠 프레임워크를 지원하기 위한 web.xml생성하기*

웹 애플리케이션에서 스트럿츠 프레임워크를 사용하기 위해서는 web.xml설정 파일에
ActionServlet을 매핑해야하며, 서버 시작시 초기화할 수 있도록 추가해주어야 한다.
앞의 서블릿에서 살펴보았지만 서블릿의 클래스레벨 Xdoclet 태그를 이용하여
web.xml을 쉽게 생성할 수 있다. 그러나 ActionServlet을 사용할 경우 얘기는
달라진다. ActionServlet은 개발자들이 매번 개발하는 것이 아니라 이미 작성되어
있기 때문에 앞의 서블릿예제처럼 web.xml을 생성하기 위해서는 스트럿츠 소스를
직접수정해야 한다.

이 같은 문제점을 해결하기 위하여 ANT의 merge기능이
이용하였다. merge기능이란 ActionServlet과 같이 소스를 직접 수정하기는
힘들지만 Descriptor파일에 추가할 내용이 있다면 그 내용을 XML에 작성할 수 있다.
이와 같이 작성된 XML의 내용은 ANT가 빌드될 경우 web.xml,
struts-config.xml의 적절한 위치에 추가되게 된다.

스트럿츠
프레임워크를 지원하기위한 web.xml을 생성하기 위해서 필요한 내용은 서블릿 정보와 서블릿
매핑이였다. web.xml의 >servlet/<태그의 추가를 위해서는 서블릿 정보를
servlets.xml, >servlet-mapping/<태그의 추가를 위해서는
servlet-mappings.xml에 각각 추가하고자 하는 내용을 추가해주면 된다.

<!-- Struts -->
<servlet>
	<servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    
	<init-param>
    	<param-name>application</param-name>
    	<param-value>Resources</param-value>
  	</init-param>  
	<init-param>
    	<param-name>config</param-name>
	    <param-value>/WEB-INF/struts-config.xml</param-value>
	</init-param>
  	<init-param>
    	<param-name>debug</param-name>
    	<param-value>0</param-value>
  	</init-param>
  	
    <load-on-startup>1</load-on-startup>  	  
</servlet>

[예제 3-9]web.xml에 추가할 servlets.xml

<!-- struts -->
<servlet-mapping>
	<servlet-name>action</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>

[예제 3-10] web.xml에 추가할 servlet-mappings.xml

ANT의 merge기능을 이용하여 [예제3- 9][예제 3-10]
추가한 web.xml의 내용은 다음과 같다.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app >
   <distributable/>
 <!-- Struts -->
<servlet>
	<servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
	<init-param>
    	<param-name>application</param-name>
    	<param-value>Resources</param-value>
  	</init-param>  
	<init-param>
    	<param-name>config</param-name>
	    <param-value>/WEB-INF/struts-config.xml</param-value>
	</init-param>
  	<init-param>
    	<param-name>debug</param-name>
    	<param-value>0</param-value>
  	</init-param>
    <load-on-startup>1</load-on-startup>  	  
</servlet>

  <!-- struts -->
<servlet-mapping>
	<servlet-name>action</servlet-name>
	<url-pattern>*.do</url-pattern>
</servlet-mapping>

</web-app>

[예제 3-11] 예제 3-9, 예제 3-10을 이용하여 생성된 web.xml

이상으로 스트럿츠 프레임워크를 기반으로하는 웹 애플리케이션을 개발하기
위하여 필요한 web.xml, struts-config.xml의 작업이 완료되었다. 이를
발판으로 계속해서 추가되는 Form, Action클래스들을 Xdoclet 태그를 이용하여
생성하기만 하면 된다. web.xml과 struts-config.xml의 생성은 전적으로
ANT와 Xdoclet이 담당하기 때문에 상당한 개발시간의 단축효과를 가져올 수 있다.

지금까지 개발한 예제 소스를 테스트해보자. 앞의 예제들과 같이 'ant
struts'를 실행하여 빌드하면 역시 chapter3.war파일이 생성되어 자동적으로
디플로이된다. Tomcat서버를 시작한 다음
http://localhost:8080/chapter3/user_write.jsp URL로
테스트해보기 바란다. 자신의 정보를 입력한 다음 '사용자 정보'버튼을 누르면 [그림
3-11]과 같은 화면을 볼 수 있을 것이다. user_write.jsp와
user_info.jsp 예제소스는 첨부되는 CD를 참고하기 바란다.

[그림 3-11] 사용자 정보를 출력하는 화면

스트럿츠 예제에 한글 문제를
해결하기 위하여 서블릿 필터(Servlet Filter)기능을 이용하였다. 서블릿 필터 또한
Xdoclet 태그를 이용하여 web.xml에 새로운 필터를 추가하고 있다. Xdoclet을
이용하여 서블릿 필터를 추가하는 과정은 첨부되는 예제 소스를 참고하기 바란다.

*2.3 Xdoclet 매뉴얼 사용하는 방법*

Xdoclet은 개발자들이 흔히 만들어왔던 web.xml, tld, ejb-jar.xml파일들외에도
무수히 많은 프레임워크를 지원하고 있다. 앞의 스트럿츠 예제에서도 볼 수 있듯이 새로운 프레임워크가
새로 생성될 때마다 Xdoclet 태그를 사용할 수 있도록 지원하고 있다.
http://xdoclet.sourceforge.net

접근하여 왼쪽메뉴에 보이는 수십개의 Tag Reference가 현재 지원하고 있는 프레임워크이다.
독자들이 새로운 프레임워크를 사용하여 프로젝트를 진행할 때 Xdoclet을 이용하고자 한다면
Xdoclet사이트에서 제공하는 매뉴얼은 좋은 자료가 된다. 따라서 Xdoclet에서 제공하는
매뉴얼을 사용하는 방법에 대하여 살펴보는 것이 새로운 프레임워크를 적용하고자 할 때 많은 도움이 될
것이다. 스트럿츠 설정파일인 struts-config.xml파일을 생성하기 위해 Xdoclet의
매뉴얼을 참조하는 과정을 통해 매뉴얼 사용방법에 대하여 설명하도록 하겠다.

*2.3.1 ANT에서 사용할 태스크*

지금까지 살펴본 예제를 보면 알겠지만 클래스에 추가된 Xdoclet태그를 이용하여 설정파일을
생성하기 위해서는 Xdoclet에서 제공하는 ANT용 태스크를 이용하여 빌드해 주어야한다.
따라서 특정 프레임워크의 설정파일을 생성하는데 사용할 태스크를 찾을 필요가 있다. 이 정보는

http://xdoclet.sourceforge.net

의 Ant Task Reference에서 찾을 수 있다. 현재 7개의 태스크를 제공하고
있다.

스트럿츠 설정파일은 >webdoclet ../< 태스크를
이용하여 생성할 수 있다.
http://xdoclet.sourceforge.net/ant/xdoclet/modules/web/WebDocletTask.html

을 보면 >webdoclet ../<엘리먼트에서 사용할 수 있는 속성 정보와 하위
엘리먼트 정보를 볼 수 있다. 이처럼 각각의 태스크에는 각 태스트에서 사용할 수 있는 속성과
각 태스트에서 사용할 수 있는 하위 엘리먼트를 찾을 수 있다. 위 문서에서 스트럿츠
설정파일을 생성하기 위한 엘리먼트는 strutsconfigxml라는 것을 찾을 수 있다.
Strutsconfigxml항목을 클릭하고 들어가면 strutsconfigxml에서 사용할
수 있는 속성 정보와 merge할 수 있는 파일 정보가 포함되어 있다. Merge할 파일
이름 또한 이미 정해져 있기 때문에 Xdoclet의 매뉴얼을 참조하여 해당 merge파일에
작성해주면 설정파일 생성시 merge할 파일의 내용을 추가하게 된다.

이 같은
단계를 거쳐 작성된 ANT의 타겟정보는 다음과 같다.

<target name="strutsgenerateDD" depends="compile">
  <taskdef name="webdoclet"
		   classname="xdoclet.modules.web.WebDocletTask" 
		   classpathref="xdoclet.class.path"
  />

  <webdoclet 
	 destdir="${build.dir}"
	 mergedir="${merge.dir}"
  > 
	 <fileset dir="${src.dir}">
		<include name="**/*Filter.java" /> 
		<include name="**/*Action.java" />
		<include name="**/*Form.java" />          
	 </fileset>
	 <deploymentdescriptor servletspec="2.3" 
			          destdir="${build.webinf.dir}" > 
	 </deploymentdescriptor>	 
	 <strutsconfigxml 
		version="1.1"
		destdir="${build.webinf.dir}"/>
  </webdoclet>
</target>

위 예제에서 deploymentdescriptor는 web.xml을 생성하는 하위
엘리먼트이다. 위 ANT용 스크립트는 Xdoclet의 매뉴얼을 이용하여 충분히 만들 수
있다.

*2.3.2 자바소스코드에 사용할 태그 매뉴얼*

Xdoclet을 이용하여 설정파일을 자동적으로 생성하기 위해서는 자바소스에 각 프레임워크별
Xdoclet태그를 추가해야한다. 자바소스에서 사용가능한 Xdoclet태그의 정보는
http://xdoclet.sourceforge.net

왼쪽 메뉴의 Tag Reference에서 찾을 수 있다. 현재까지 지원하는 프레임워크는
수십개에 달한다.

먼저 스트럿츠 설정파일을 생성하기 위한 사용할
Xdoclet태그에 대한 정보는 apache(@soap @struts)에서 찾을 수 있다.

[http://xdoclet.sourceforge.net/tags/apache-tags.html

http://xdoclet.sourceforge.net/tags/apache-tags.html]
페이지에서 스트럿츠 항목으로 이동해 보면 클래스 레벨에서 사용가능한 태그와 메써드
레벨에서 사용 가능한 태그 정보를 찾을 수 있다. 각 태그를 클릭하면 태그에서 사용할 수
있는 속성정보를 얻을 수 있다. 이 페이지에서 제공하는 태그들을 클래스에 추가하여 스트럿츠
설정파일을 자동으로 생성할 수 있게 된다.

스트럿츠 설정파일을 생성하기 위하여
Xdoclet태그를 사용한 예제는 [예제 3-6][예제 3-7]에서 볼 수 있다. 이책의
모든 예제가 Xdoclet을 이용하고 있기 때문에 첨부되는 예제소스를 참고한다면
Xdoclet을 사용하는데 많은 도움이 될 것이다.

ANT용 스크립트를
만들거나 Xdoclet태그를 사용하기 위하여 다른 개발자가 만들어 놓은 스크립트나 소스를
복사한 다음 수정하는 방법도 좋은 방법이다. 그러나 그와 같은 방법에는 한계가 있기
마련이다. 따라서 가능하면 각각의 툴에서 제공하는 매뉴얼을 참조하는 습관을 들여
Xdoclet이 지원하는 어떠한 프레임워크도 어렵지 않게 사용할 수 있기를 바란다.

*3. 생각해볼 문제*

처음 이 장을 쓰기 시작할 때 '어떻게 하면 현업 개발자들이 스트럿츠를 기반으로 개발할 경우 툴을 사용할 수 있게
할까?'하고 많은 고민을 했다. 원고를 준비하면서 내린 결론은 '쉽고, 자세하게 써야 개발자들이 적용할 수
있다'였다. 따라서 중급 개발자들에게는 너무 자세하게 설명한 부분이 없지 않다. 하지만 아직 국내에 스트럿츠를
제대로 사용하는 개발자들이 많지 않은 상태이기 때문에 스트럿츠를 시작하려고 생각하거나, 이제 시작 단계인
개발자들을 위한 배려였다.

필자가 위 두가지 툴을 사용하면서 느낀 점은 'Easy Struts를 이용하는
것보다는 Xdoclet을 이용하는 것이 더 좋겠다.'라는 것이다. 이유는 계속적인 통합작업이 많은 현업의
애플리케이션을 위해서는 Easy Struts보다는 Xdoclet이 더 적합하기 때문이다. Easy Struts가
자동으로 생성해주는 소스가 많기는 하지만, 소스를 수정하거나, struts-config.xml을 Easy
Struts를 이용하지 않고 수정할 경우 버그가 발생하는 경우도 종종 있다.

Easy
Struts를 이용하여 소스를 생성해보면 Xdoclet 태그가 생성되어 있는 것을 확인할 수 있다. 따라서 또
다른 방법으로 Easy Struts를 이용하여 기본적인 Action, ActionForm 템플릿을 생성하고, 최종
빌드는 ANT와 Xdoclet을 이용하는 것도 좋을 것으로 생각된다. Xdoclet을 이용할 경우 스트럿츠의
모듈을 위한 설정파일을 자동 생성하기가 힘들었다. 그러나 Easy Struts 플러그인은 모듈 설정파일 또한 자동
생성하기 때문에 모듈의 사용에 익숙하지 않은 개발자라면 Easy Struts플러그인을 이용하는 것이 좋은 선택이
될 것이다.

Xdoclet을 이용하여 최고의 개발속도를 내기 위해서는 CVS(Concurrent
Version System), SourceSafe와 같은 버전 관리 시스템을 같이 사용해야한다. 버전 관리
시스템을 같이 사용하지 않을 경우 여러명의 개발자들이 각기 개발한 소스를 빌드하기 힘들다. 따라서 여러명의
개발자가 ANT와 Xdoclet을 이용할 경우 버전 관리 시스템을 꼭 사용해야 툴을 사용하는 시너지 효과를 낼 수
있다.

좋은 툴을 적재적소에 사용하는 것 또한 개발자의 능력이다. 언어가 계속해서 변화하듯이
개발방법, 개발 툴 또한 변화되고 있다. 그러나 국내의 많은 개발자들을 보면 새로운 툴을 사용하는 것을 꺼리는
듯하다. 그러나 웹 애플리케이션 구조는 점점 더 복잡해지고 있으며, 기존의 툴로 점점 더 복잡해져가는
애플리케이션을 개발하기로 상당히 많은 시간을 요구하는 경우가 많다. 비즈니스 로직에 집중해야함에도 불구하고 다른
작업에 너무나 많은 시간을 빼앗기고 있다면 새로운 개발툴을 찾을 때가 된 것이다. ANT, Easy
Struts플러그인과 Xdoclet 또한 그 일환이다. 개발자들의 현명한 선택이 있기를 바란다.

강좌에 대하여

작성자 : 박재성
작성일 : 2005년 2월 23일

문서이력 :

  • 2005년 2월 23일 박재성 문서 최초 생성

참고 자료

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.