홈페이지 꼭대기로

JSP 2.0: 뭐가 바뀌었나? - 2부

원문 : http://www.onjava.com/pub/a/onjava/2003/12/03/JSP2part2.html

by Hans Bergsten, JavaServer Pages, 3판의 저자

번역 손권남(kwon37xi_aT_yahoo dOt co DoT kr

2004/07/29

이것은 JavaServer Pages(JSP) 2.0 명세에 추가된 사항들을 설명하는 시리즈의 두번째 글이다. 1부에서는 새로운 표현식(Expression Language)에 대해서 설명했으나, 알아둘게 더 많이 있다. 이번 회에서는 오류 처리 부문에서의 발전된 모습과 새로운 배치 기술자(deployment descriptor) 기능에 대해 알아볼 것이다. 나는 당신이 JSP 1.2에 익숙하고 JSP Standard Tag Library(JSTL)에 대해 들어보기는 했다고 가정하고 글을 썼다.

JSP Error Pages

JSP나 서블릿에서 JSP 오류 페이지를 사용해 보았다면, 이 페이지를 불러들인 예외에 관해 출력하거나 로그 정보를 보여주기를 바랬을 것이다. 하지만 JSP 1.2에서는 그게 그리 쉬운일이 아니다. 그 이유는 errorPage 선언을 가진 서블릿과 JSP가 예외를 request 속성(attribute으로 전달하고, 서로 다른 속성 이름을 사용하기 때문이다. 오직 JSP 속성 이름으로 전달된 예외만이 자동으로 JSP 오류 페이지에 나타날 뿐이다(exception 스크립트 변수나 ${pageContext.exception} EL을 이용해서).

JSP 2.0에서는 서블릿 명세와 같은 속성이름 - javax.servlet.error.exception으로 변경함으로써 이 문제를 해결했다. 또한, 내장 EL pageContext 변수에 errerData라는 새로운 프라퍼티가 있어, 발생한 문제에 대한 다른 정보들도 제공해 준다. errerData 속성은 javax.servlet.jsp.ErrorData 클래스의 인스턴스이며 다음과 같은 프라퍼티로 빈(Bean)으로써 사용할 수 있다.

프라퍼티자바 형 설명
requestURI String 요청이 실패한 URI.
servletName String 실패한 JSP나 서블릿의 이름.
statusCode int 실패 상태 코드.
throwable Throwable 오류 페이지를 불러들인 예외.

저 프라퍼티들을 사용하는 JSP 오류 페이지의 예제가 있다 :

<%@ page isErrorPage="true" contentType="text/html" %>
<%@ taglib prefix="log" uri="http://jakarta.apache.org/taglibs/log-1.0" %>

Sorry, but things didn't work out as planned. I've logged as much as
I know about the problem, so rest assured that my master will look
into what's wrong as soon as he's sober.

<jsp:useBean id="now" class="java.util.Date" />
<log:fatal>
  -----
  ${now}
  Request that failed: ${pageContext.errorData.requestURI}
  Status code: ${pageContext.errorData.statusCode}
  Exception: ${pageContext.errorData.throwable}
  -----
</log:fatal>

이 페이지에서 사용자들을 다소 안심시켜주는 메시지와 아파치 자카르타 Taglib 프로젝트의 Log 태그 라이브러리를 사용해서 상세한 로그를 보여준다.

특정 파일이 서블릿과 JSP 페이지의 오류 페이지임을 선언하기 위해, web.xml 파일에서 <error-page> 요소를 사용할 수도 있다.

...
  <error-page>
    <exception-type>java.lang.Throwable</exception-type>
    <location>/error.jsp</location>
  </error-page>
  <error-page>
    <exception-code>500</exception-code>
    <location>/error.jsp</location>
  </error-page>
...

특정 JSP 페이지에 대해서 다른 오류 페이지를 보여주고자 한다면, 페이지 지시자의 errorPage 속성을 이용해서 web.xml의 선언을 오버라이드 할 수 있다.

<%@ page errorPage="/other_error.jsp" contentType="text/html" %>

JSP 문법 오류 보고

JSP 1.2와 2.0간의 작지만 중요한 차이점은 JSP 2.0이 JSP 컨테이너가 jsp:id 기능을 지원하도록 한다는 점이다. 이것은 1.2에서는 단지 "권장사항"일 뿐이었다. JSP 개발자들에게 이것이 무엇을 의미하는가? 바로 JSTL이나 커스텀 태그 라이브러리의 문법 오류 내용이 더욱 쓸만해진다는 것이다.

어떻게 작동하냐구? 컨테이너가 JSP 페이지를 실행 가능한 형태(서블릿 클래스)로 변환할 때, 페이지 내에 선언된 모든 태그 라이브러리를 살펴본다. 한 개 혹은 여러개의 태그 라이브러리 선언이 태그 라이브러리 유효성 검사기(TLV; Tag Library Validator)를 가지고 있다면, 컨테이너가 페이지를 받아들이기 전에 TLV가 페이지의 유효성을 검사할 기회를 주게 된다.

이것은 TLV가 페이지를 분석할 때 XML 뷰(View)를 제공 한다. XML 뷰는, 이름에서 보듯이, 모든 정규 JSP 요소와 템플릿 텍스트(HTML 같은..)를 웰 폼드(Well-Formed) XML 문서로 변환한 것이다.

XML 뷰는 TLV가 모든 커스텀 액션이 올바르게 사용되었는지를 확신하도록 파싱 하는 것을 쉽게 만들어 준다.(예를 들어, 엘리먼트들이 올바르게 중첩되었는가, 함께 나와서는 안되는 속성들이 동일한 액션 요소에 같이 사용되지는 않았는가?)

여기 jsp:id가 온 곳이 있다. 컨테이너는 페이지의 각 커스텀 액션 요소에 ID를 부여하고 ID와 요소의 위치(파일, 줄 번호, 행 번호)간의 맵을 유지한다. 컨테이너는 jsp:id 속성을 ID를 값으로 하여 XML 뷰의 모든 커스텀 액션 요소에 추가한다. TLV가 오류를 발견하면, 오류 메시지에 잘못된 액션 요소의 jsp:id 속성 값을 추가하여 컨테이너에 넘겨주게 된다. 컨테이너는 매핑 정보를 이용해서 잘못된 커스텀 액션 요소의 위치 정보를 사용자에게 보여주는 에러 메시지에 추가한다. 이로 인해 문제점을 찾고 수정하기가 쉬워진다.

모든 JSTL 라이브러리는 TLV를 갖고 있다. 나는 당신이 작성할 커스텀 라이브러리에 TLV를 만들고, 당신이 사용할 서드 파티 라이브러리 개발자들에게도 그렇게 하도록 주장할것을 강력히 권한다.

당신이 XML 뷰와 TLV를 잘 모르겠다면, 내가 2001년에 JSP 1.2에 대해 쓴 글에 간단한 설명을 해 뒀으니 보기 바란다.(JSP 1.2: Great News for the JSP Community).

JSP 배치 기술자(deployment descriptor) 새소식

JSP 2.0 은 이전 JSP 명세에서 그랬던 것 처럼 서블릿 명세에 의해 정의된 배치 기술자(web.xml)파일 형식을 사용한다.

어쨌든, JSP 2.0에는 두가지 중요한 변화가 있다: web.xml의 규칙이 XML 스키마(Schema)로 정의되었고, 대부분의 JSP 관련 설정 아이템들이 새로운 XML 요소로 이동해서 JSP 명세의 제어 하에 놓이게 되었다(서블릿과 JSP 명세간의 결합도(coupling)를 최소화 하기 위해서).

XML 스키마는 XML 문서의 문법 규칙을 설명하는 XML 언어이다(예. 요소가 어떻게 중첩되는가, 요소가 어떤 값을 가질 수 있는가, 값이 중복 될 수 있는가, 그리고 그 외 여러가지). 이건 매우 복잡한 명세이지만 운좋게도, 당신이 web.xml을 작성하기 위해 그 XML 스키마의 문법 규칙을 이해해야 할 필요는 없다. 왜냐하면 서블릿과 JSP 명세는 이해하기 쉬운 도표를 제공하기 때문이다(나의 JavaServer Pages, 제 3판 책은 읽기 쉬운 문법 도표를 포함하고 있다). 그래도 XML 스키마를 공부하고 싶다면 W3C 웹 사이트를 참조하라.

규칙을 예전의 DTD 대신 XML 스키마를 이용해서 선언하는 것의 장점은 XML 스키마는 더욱 세부적이라 web.xml 파일을 파싱할 때 더 많은 오류를 찾을 수 있고, 덕분에 컨테이너들 간의 더 나은 이식성을 가져온다는 것이다.

내 생각에 당신이 더욱 기뻐할 다른 장점으로는 XML 스키마가 web.xml의 최상위 요소들이 어떤 순서로 배열되도 상관없게 만들어 준다는 것이다. 이전 버전의 서블릿과 JSP 명세에서는 예를 들어 <error-page> 요소가 <welcome-file-list> 요소보다 먼저 오기라도 하면 오류를 발생시켰지만, 새로운 버전에서는 그런것도 아무 상관 없다. 그렇더라도 최상위 요소 안에 오는 요소들의 순서는 여전히 엄격한 순서에 따라야만 한다. 어쨌든 당신은 최상위 요소들을 마음대로 할 수 있는 자유를 가졌다.

<servlet> 요소 안에 중첩된 <jsp-file> 요소를 제외하고 모든 JSP 관련 요소들은 <jsp-config>라는 최상위 요소 아래에 함께 묶이게 되었다. <jsp-config>안에 중첩해서 <taglib>요소도 JSP 1.2에서와 같은 문법과 의미로 사용할 수 있다. 하지만 사실 JSP 1.2 이후의 컨테이너에서는 <taglib>가 불필요하다. 컨테이너가 배치된 JAR파일로 부터 자동으로 태그 라이브러리 정의를 뽑아내기 때문이다.

새로운 <jsp-property-group> 하위요소(subelement)는 훨씬 더 관심있게 볼만하다. 이 요소는 특정한 URL패턴에 부합하는 JSP 페이지의 집합에 특정한 설정을 적용할 수 있게 한다. 예를 들어보면:

...
  <jsp-config>
    <jsp-property-group>
      <url-pattern>*.jsp</url-pattern>
      <scripting-invalid>true</scripting-invalid>
    </jsp-property-group>
  </jsp-config>
...

<url-pattern> 요소는 설정을 적용할 JSP 페이지의 집합을 구분한다.다른 중첩된 요소들은 설정 옵션을 정의한다. 이 예제에서는, <scripting-invalid> 요소가 모든 JSP 페이지에서 JSP 스크립팅 요소(Java 코드 같은)를 사용할 수 없게 만든다.

대체로(all in all), 다음과 같은 설정 요소들을 <jsp-property-group> 요소 안에 중첩해서 <scripting-invalid> 요소와 같은 방식으로 사용할 수 있다:

요소 설명
<el-ignored> true이면, URL 패턴이 일치하는 JSP 페이지 내의 EL 표현식을 EL 표현식이 아니라 일반적인 텍스트로써 다루게 된다. 이것은 JSP 1.2에서 EL 표현식처럼 보이는 텍스트를 JSP 2.0 으로 천천히 마이그레이션 하는데 유용하게 사용될 수 있다. 'elIgnored' 페이지 지시자 속성을 이용해서 JSP 2.0으로 변환한 페이지들에서 선택적으로 EL을 사용하게 만들 수도 있다.
<scripting-invalid> true이면, URL 패턴이 일치하는 JSP 페이지에서 스크립팅 요소를 사용하면 번역시(translation-time) 오류를 발생시킨다.
<page-encoding> URL 패턴이 일치하는 모든 JSP 페이지에 대해 지정된 페이지 문자 인코딩을 사용한다. 모든 JSP 페이지에 인코딩을 지정하는 대신 사용할 수 있고, JSP 페이지에 몇몇 특수한 파일 인코딩(예를들면 EBCDIC)을 지정할 수 있는 유일한 방법이다.
<include-coda> URL 패턴이 일치하는 모든 JSP 페이지의 끝에 자동으로 포함될 파일의 컨텍스트에 상대적인 경로를 지정한다. 한개의 <jsp-property-group> 요소 안에서 여러개의 요소를 사용할 수도 있고, 여러개의 <jsp-property-group> 요소에서 사용할 수도 있다.
<include-prelude> URL 패턴이 일치하는 모든 JSP 페이지의 시작 부분에 자동으로 포함될 파일의 컨텍스트에 상대적인 경로를 지정한다. 한개의 <jsp-property-group> 요소 안에서 여러개의 요소를 사용할 수도 있고, 여러개의 <jsp-property-group> 요소에서 사용할 수도 있다.
<is-xml> true이면, URL 패턴이 일치하는 모든 JSP 페이지가 JSP XML 문법을 사용한다고 지정하는 것이다(이것이 JSP 문서이다).

마무리

이번 회에서는 JSP 2.0 오류 처리방식의 개선점과 새로운 배치 기술자의 기능들을 설명했다. 이 시리즈의 다음번 글에서는 JSP 2.0이 XML 컨텐트를 위해 JSP를 사용하는 것이 어떻게 쉬워졌는지와 커스텀 태그 라이브러리에 관련된 새로운 기능들을 알아볼 것이다.

JSP 2.0의 새로운 기능들을 접해보고 싶다면, Apache Tomcat 5를 사용해보라고 권하고 싶다. 톰캣은 새로운 JSP 스펙을 최초로 구현한 JSP 컨테이너이다. Jakarta Project 사이트에서 구할 수 있다.