달력

11

« 2024/11 »

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
2007. 1. 29. 14:49

JSTL 기초, Part 2: 핵심에 접근하기 그거/Java2007. 1. 29. 14:49

커스텀 태그를 이용한 플로우 제어와 URL 관리

developerWorks

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.



난이도 : 초급

Mark Kolb, 소프트웨어 엔지니어

2003 년 3 월 18 일
2003 년 8 월 08 일 수정

SP Standard Tag Library (JSTL) core 라이브러리는 이름이 말해주듯이, 범위(scoped) 변수를 관리하고 URL과 인터랙팅하는 등의 기본 기능과, 반복과 조건화 같은 근본적인 작동에 필요한 커스텀 태그를 제공한다. 이러한 태그들은 페이지 작성자가 직접 사용하기도 하지만 다른 JSTL 라이브러리와 함께 복잡한 표현 로직에 대한 토대를 제공한다.

이 시리즈의 첫 번째 글에서 JSTL을 처음 보았을 것이다. 거기에서 데이터에 액세스 하고 작동하기 위해 expression language (EL)의 사용법을 설명했다. 여러분이 배운 것 처럼 EL은 JSTL 커스텀 태그의 애트리뷰트에 동적 값을 할당하는데 사용된다. 따라서 빌트인 액션과 기타 커스텀 태그 라이브러리용 요청 시간 애트리뷰트 값을 지정하는 JSP 식과 같은 역할을 한다.

EL의 사용법을 설명하기 위해, core 라이브러리에서 세 개의 태그 (<c:set>, <c:remove>, <c:out>)를 소개했었다. <c:set><c:remove>는 범위 변수를 관리하는데 사용된다. <c:out>은 특별히 EL을 사용하여 계산된 값인 데이터 디스플레이에 사용된다. 기초 학습을 토대로 이제는 core 라이브러리의 나머지 태그를 볼 것이다. 두 가지 주요 카테고리로 나뉜다: 플로우 제어(플로우 제어)와 URL 관리.

예제 애플리케이션

JSTL 태그를 설명하기 위해서 실제 애플리케이션 예제를 사용할 것이다. 대중성과 인지도가 높아졌기 때문에 간단한 자바 기반의 Weblog를 사용할 것이다. (참고자료에서 JSP 페이지와 소스 코드를 다운로드 한다.) Weblog (blog)은 웹 기반 저널로서 Weblog의 작성자가 흥미를 가질만한 주제들에 대한 짧은 주석이다. 일반적으로 웹 상의 아티클이나 토의가 있는 곳 어디든 연결된다. 그림 1은 실행 중인 애플리케이션의 모습이다.



그림 1. Weblog 애플리케이션
Screenshot of the Weblog 예제 애플리케이션

스무 개 정도의 자바 클래스가 전체 구현에 필요하지만 Weblog 애플리케이션 클래스에서는 단 두개(EntryUserBean)만이 프리젠테이션 레이어에 사용된다. JSTL 예제를 이해하려면 이들 두 개의 클래스가 필요하다. 그림 2는 EntryUserBean의 클래스 다이어그램이다.



그림 2. Weblog 애플리케이션(클래스 다이어그램)
Class diagram for Weblog 예제 애플리케이션

Entry 클래스는 Weblog 내의 날짜가 나와있는 엔트리를 나타낸다. 이것의 id 애트리뷰트는 데이터베이스 내의 엔트리를 저장하고 검색하는데 사용된다. 반면 titletext 애트리뷰트는 엔트리의 실제 콘텐트를 나타낸다. 자바 Date 클래스 중 두 개의 인스턴스는 createdlastModified 애트리뷰트에 의해 레퍼런스되며 엔트리가 처음으로 만들어지고 마지막으로 편집 될 때 나타난다. author 애트리뷰트는 UserBean 인스턴스를 참조하면서 엔트리를 만든 사람을 나타낸다.

The UserBean 클래스는 애플리케이션의 권한이 있는 사용자 정보(사용자 이름, 성명, 이메일 주소)를 저장한다. 이 클래스에는 관련 데이터베이스와 인터랙팅하기 위한 id 애트리뷰트도 포함되어 있다. 마지막 애트리뷰트인 rolesString 값 리스트를 참조하면서 애플리케이션 역할과 이에 상응하는 사용자를 구분한다. Weblog 애플리케이션의 경우 일반적인 역할은 "User" (모든 일반적인 애플리케이션 사용자 역할)와 "Author" (Weblog 엔트리를 만들고 편집할 수 있는 사용자를 지정하는 역할) 이다.

본 시리즈의 다른 주제들

Part 1, "expression language" (2003년 2월) Part 3, "프리젠테이션이 모든 것이다!" (2003년 4월) Part 4, "SQL과 XML 콘텐트에 접근하기" (2003년 5월)




위로


플로우 제어(Flow control)

동적 애트리뷰트 값을 지정하는데 JSP 식 대용으로 EL이 사용될 수 있기 때문에 스크립팅 엘리먼트를 사용할 필요가 줄어들었다. 스크립팅 엘리먼트는 JSP 페이지에서 중요한 소스가 될 수 있기 때문에 간단한 대안을 제공한다는 것은 JSTL에 있어서 큰 이점이다.

EL은 JSP 컨테이너에서 데이터를 검색하고 객체 계층을 오가며 간단한 작동을 수행한다. 데이터에 접근하여 조작하는 것 외에도 JSP 스크립팅 엘리먼트의 또 다른 사용 측면은 플로우 제어이다. 특히, 페이지 작성자가 반복되거나 조건적인 콘텐트를 구현하기 위해서 스크립틀릿을 의존한다는 것은 일반적인 일이다. 하지만 그와 같은 작동은 EL의 기능을 넘어서기 때문에, core 라이브러리는 반복, 조건화, 예외 처리 등의 형태로 플로우 제어를 관리 할 다양한 사용자 액션을 제공한다.

반복

웹 애플리케이션의 측면에서, 반복(iteration)은 데이터의 모음을 가져다가 디스플레이 하는데 주로 사용된다. 주로 테이블에 리스트나 열(row) 시퀀스의 형태로 나타난다. 반복 콘텐트를 구현하는 JSTL의 기본 액션은 <c:forEach> 커스텀 태그이다. 이 태그는 두 개의 다른 유형의 반복을 지원한다: 정수 범위내의 반복(이를 테면, 자바의 for 문)과 컬렉션 내의 반복(자바의 IteratorEnumeration 클래스).

정수 범위 내에서 반복하려면 <c:forEach>(Listing 1)의 커스텀 태그의 신택스가 사용된다. beginend 애트리뷰트는 정적 정수 값 또는 정수 값을 계산하는 수식이 되어야한다. 이들은 각각 반복을 위한 인덱스의 초기 값과 반복이 멈추는 지점의 인덱스 값을 지정한다. <c:forEach>를 사용하여 정수 범위에서 반복할 때, 이 두개의 애트리뷰트가 필요하며 다른 모든 것들은 선택사항이다.



Listing 1. <c:forEach> 액션을 통한 반복 신택스
<c:forEach var="name" varStatus="name"
begin="expression" end="expression" step="expression">
body content
</c:forEach>

		

step 애트리뷰트 또한 정수 값을 갖고 있어야한다. 매번 반복한 후에 인덱스에 추가될 양(amount)을 정한다. 따라서 반복 인덱스는 begin 애트리뷰트 값에서 시작하고 step 애트리뷰트의 값에 의해 증가하며 end 애트리뷰트의 값을 초과할 때 정지한다. step 애트리뷰트가 생략되면 step 크기는 1로 초기화된다.

var 애트리뷰트가 지정되면 지정된 이름을 가진 범위 변수가 만들어지고 인덱스의 현재 값으로 할당된다. 이 범위 변수는 <c:forEach> 태그의 바디 내에서 액세스 될 수 있다. Listing 2는 <c:forEach> 액션의 예제이다.



Listing 2. <c:forEach> 태그
<table>
<tr><th>Value</th>
    <th>Square</th></tr>
<c:forEach var="x" begin="0" end="10" step="2">
  <tr><td><c:out value="${x}"/></td>
      <td><c:out value="${x * x}"/></td></tr>
</c:forEach>
</table>

		

이 예제 코드는 다섯 개 짝수의 제곱을 테이블로 만들었다. 그림 3이 그 결과이다 .



그림 3. Listing 2의 결과
Output of Listing 2

컬렉션의 멤버들 사이를 반복할 때 <c:forEach> 태그의 추가 애트리뷰트인 items 애트리뷰트가 사용된다. (Listing 3). 이러한 형식의 <c:forEach> 태그를 사용할 때, items 애트리뷰트는 유일하게 필요한 애트리뷰트이다.



>Listing 3. <c:forEach> 액션을 통한 반복 신택스
<c:forEach var="name" items="expression" varStatus="name"
 begin="expression" end="expression" step="expression">
  body content
</c:forEach>			
		

자바 플랫폼에서 제공되는 표준 컬렉션 타입은 <c:forEach> 태그에 의해 지원된다. 어레이 엘리먼트를 통해 반복할 때 이 액션을 사용할 수 있다. 표 1은 items 애트리뷰트에 의해 지원되는 값들의 리스트이다. 테이블의 마지막 열이 표시될 때, JSTL은 이것의 인터페이스(javax.servlet.jsp.jstl.sql.Result)를 정의한다.

표 1. <c:forEach> 태그의 items 애트리뷰트에서 지원되는 컬렉션

items item 값의 결과
java.util.Collection 호출에서 iterator()까지의 엘리먼트
java.util.Map java.util.Map.Entry의 인스턴스
java.util.Iterator Iterator 엘리먼트
java.util.Enumeration Enumeration 엘리먼트
Object 인스턴스 어레이 Array 엘리먼트
초기 값들의 어레이 래핑된 어레이 엘리먼트
콤마로 나뉘어진 String 서브스트링
javax.servlet.jsp.jstl.sql.Result SQL 쿼리의 열(row)

Listing 4는 컬렉션을 통한 반복에 사용되는 <c:forEach> 태그이다. entryList 라는 범위 변수가 Entry 객체의 리스트로 설정되었다. <c:forEach> 태그가 이 리스트의 각 엘리먼트를 처리한다. blogEntry 라는 범위 변수로 이것을 할당하고 두 개의 테이블 열을 만든다. 하나는 Weblog 엔트리의 title 이고 다른 하나는 이것의 text이다. 이 속성들은 한 쌍의 <c:out> 액션과 이에 상응하는 EL 식을 통해 blogEntry 변수에서 검색된다. Weblog 엔트리의 타이틀과 텍스트에 HTML이 포함되어있기 때문에 <c:out>escapeXml 애트리뷰트는 false로 설정된다. (그림 4).



Listing 4. <c:forEach> 태그를 사용하여 Weblog 엔트리 디스플레이 하기
<table>
  <c:forEach items="${entryList}" var="blogEntry">
    <tr><td align="left" class="blogTitle">
      <c:out value="${blogEntry.title}" escapeXml="false"/>
    </td></tr>
    <tr><td align="left" class="blogText">
      <c:out value="${blogEntry.text}" escapeXml="false"/>
    </td></tr>
  </c:forEach>
</table>
		



그림 4. Listing 4의 결과
Output of Listing 4

남아있는 <c:forEach> 애트리뷰트인 varStatus는 정수 범위의 반복이나 컬렉션 범위의 반복에서 똑같은 역할을 한다. var 애트리뷰트와 마찬가지로, varStatus는 범위 변수를 만드는데 사용된다. 현재 인덱스 값이나 현재 엘리먼트를 저장하는 대신에 이 변수는 javax.servlet.jsp.jstl.core.LoopTagStatus 의 인스턴스로 할당된다. 이 클래스는 일련의 속성을 정의한다. (표 2).

표 2. LoopTagStatus 객체의 속성

속성 Getter Description
current getCurrent() 현재 반복 라운드 아이템
index getIndex() 현재 반복 라운드의 제로 기반(zero-based) 인덱스
count getCount() 현재 반복 라운드의 1 기반(one-based) 인덱스
first isFirst() 현재 라운드가 반복을 통한 첫 번째 패스임을 나타내는 플래그
last isLast() 반복현재 라운드가 반복을 통한 마지막 패스임을 나타내는 플래그
begin getBegin() begin 애트리뷰트의 값
end getEnd() end 애트리뷰트의 값
step getStep() step 애트리뷰트의 값

Listing 5는 varStatus 애트리뷰트가 사용되는 방법을 나타낸 예제이다. Listing 4의 코드를 수정하여 Weblog 엔트리의 숫자세기를 타이틀을 디스플레이하는 테이블 열에 추가한다. 이것은 varStatus 애트리뷰트의 값을 지정하고 결과 범위 변수의 카운트 속성에 액세스 하면 된다. 결과는 그림 5 이다.



Listing 5. varStatus 애트리뷰트를 사용하여 Weblog 엔트리의 카운트 디스플레이하기
<table>
  <c:forEach items=
    "${entryList}" var="blogEntry" varStatus="status">
    <tr><td align="left" class="blogTitle">
      <c:out value="${status.count}"/>.
      <c:out value="${blogEntry.title}" escapeXml="false"/>
    </td></tr>
    <tr><td align="left" class="blogText">
      <c:out value="${blogEntry.text}" escapeXml="false"/>
    </td></tr>
  </c:forEach>
</table>

		



그림 5. Listing 5의 결과
Output of Listing 5

<c:forEach> 이외에도, core 라이브러리는 두 번째 반복 태그인 <c:forTokens>를 제공한다. 이것의 액션은 자바의 StringTokenizer 클래스의 JSTL 이다. <c:forTokens> 태그(Listing 6)는 컬렉션 지향 버전의 <c:forEach>와 같은 애트리뷰트를 갖고 있다. <c:forTokens>의 경우 토큰화 될 스트링은 items 애트리뷰트를 통해 지정되는 반면 토큰을 만드는데 사용되는 지정자(deliniter)는 delims 애트리뷰트를 통해 제공된다. <c:forEach> 경우와 마찬가지로, begin, end, step애트리뷰트를 사용하여 토큰이 상응하는 인덱스 값들과 매칭되는 것에 프로세스 되도록 제한 할 수 있다.



Listing 6. <c:forTokens> 액션
<c:forTokens var="name" items="expression"
    delims="expression" varStatus="name"
    begin="expression" end="expression" step="expression">
  body content
</c:forTokens>

		

조건화

동적 콘텐트를 포함하고 있는 웹 페이지라면 다양한 형식의 콘텐트를 볼 수 있는 다양한 사용자 카테고리가 필요할 것이다. Weblog에서 방문자들은 엔트리를 읽고 피드백을 제출 할 뿐만 아니라 권한을 받은 사용자는 새로운 엔트리를 게시하거나 기존 콘텐트를 편집할 수 있어야 한다.

JSP 페이지 내에 그러한 기능을 구현하고 리퀘스트 기반으로 디스플레이 하고자하는 것을 제어하도록 조건 로직을 사용함으로서 가용성과 소프트웨어 관리는 향상된다. core 라이브러리는 두 개의 다른 조건화 태그인 <c:if><c:choose>를 제공하는데 다음의 기능들을 구현한다.

이 두 가지 액션 중 좀더 단순한 <c:if>는 간단한 테스트 식을 계산한 다음 식이 true로 되었을 때만 바디 콘텐트를 처리한다. 그렇지 않다면 태그의 바디 콘텐트는 무시된다. Listing 7에서 보듯, <c:if>는 테스트의 결과를 varscope 애트리뷰트를 통해 범위 변수로 할당할 수 있다. 이 기능은 테스트 비용이 비쌀 경우 유용하다. 결과는 범위 변수에 캐시되고 <c:if>나 다른 JSTL 태그로의 연속 호출시에 검색된다.



Listing 7. <c:if> 조건 액션 신택스
<c:if test="expression" var="name" scope="scope">
  body content
</c:if>

		

Listing 8은 <c:forEach> 태그의 LoopTagStatus 객체의 first 속성으로 사용된 <c:if> 를 보여준다. 이 경우, 그림 6 에서 보듯, Weblog 엔트리의 구현 날짜는 첫 번째 엔트리 위에 디스플레이 된다. 하지만 다른 엔트리 앞에 반복되지 않는다.



Listing 8. <c:if>를 사용하여 Weblog 엔트리 날짜 디스플레이 하기
<table>
<c:forEach items=
"${entryList}" var="blogEntry" varStatus="status">
<c:if test="${status.first}">
<tr><td align="left" class="blogDate">
<c:out value="${blogEntry.created}"/>
</td></tr>
</c:if>
<tr><td align="left" class="blogTitle">
<c:out value="${blogEntry.title}" escapeXml="false"/>
 </td></tr>
<tr><td align="left" class="blogText">
<c:out value="${blogEntry.text}" escapeXml="false"/>
</td></tr>
</c:forEach>
</table>

		



그림 6. Listing 8의 결과
Output of Listing 8

Listing 8 처럼, <c:if> 태그는 조건화된 콘텐트에 대해 매우 간략한 노트를 제공한다. 디스플레이 되어야하는 콘텐트가 무엇인지를 결정해야하는 중립적인 테스트가 필요할 경우, JSTL core 라이브러리는 <c:choose> 액션을 제공한다. <c:choose> 신택스는 Listing 9와 같다.



Listing 9. <c:choose> 액션 신택스
<c:choose>
  <c:when test="expression">
    body content
  </c:when>
  ...
  <c:otherwise>
    body content
  </c:otherwise>
</c:choose>

		

테스트 되는 각 조건은 상응하는 <c:when> 태그에 의해 나타난다. testtrue로 평가된 첫 번째 <c:when> 태그의 콘텐트만 프로세스된다. 어떤 <c:when> 테스트도 true로 리턴되지 않으면 <c:otherwise> 태그의 바디 콘텐트가 프로세스 된다. <c:otherwise> 태그가 선택적이라는 것을 주목하라. <c:choose> 태그는 최대 한 개의 중첩 <c:otherwise> 태그를 가질 수 있다. 모든 <c:when> 테스트가 false가 되고 어떤 <c:otherwise> 액션도 나타나지 않으면 <c:choose> 바디 콘텐트는 프로세스 되지 않는다.

Listing 10은 <c:choose> 태그의 실행 예제이다. 여기에서 프로토콜 정보는 리퀘스트 객체에서 검색되고 간단한 스트링 비교를 사용하여 테스트된다. 테스트 결과에 따라 상응하는 텍스트 메시지가 디스플레이된다.



Listing 10. <c:choose>를 이용한 콘텐트 조건화
<c:choose>
  <c:when test="${pageContext.request.scheme eq 'http'}">
    This is an insecure Web session.
  </c:when>
  <c:when test="${pageContext.request.scheme eq 'https'}">
    This is a secure Web session.
  </c:when>
  <c:otherwise>
    You are using an unrecognized Web protocol. How did this happen?!
  </c:otherwise>
</c:choose>
		

예외 처리

마지막 플로우 제어 태그는 <c:catch>이다. 이것은 JSP 페이지 내에서 기본적인 예외처리를 담당한다. 좀더 구체적으로 말하면 이 태그의 바디 콘텐트 내에서 발생하는 모든 예외가 잡히면 무시된다. 하지만 예외가 발생하고 <c:catch> 태그의 선택적인 var 애트리뷰트가 지정되면 예외는 지정된 변수로 할당되어 페이지 자체 내에서 에러 처리를 할 수 있다. Listing 11은 <c:catch>의 신택스이다. (예제는 Listing 18이다)



Listing 11. <c:catch> 실행 신택스
<c:catch var="name">
  body content
</c:catch>
		




위로


URL 작동

JSTL core 라이브러리의 나머지 태그는 URL에 초점을 맞춘다. 이 중 첫 번째는 <c:url> 태그인데 URL 생성에 사용된다. 특히, <c:url>은 J2EE 웹 애플리케이션용 URL을 구현할 때 중요하게 쓰이는 세 가지 엘리먼트를 제공한다:

  • 현재 서블릿 콘텍스트 이름이 됨
  • 세션 관리를 위한 URL 재작성
  • 요청 매개변수 이름과 값의 URL 인코딩

value 애트리뷰트가 사용되었다. 기본 URL을 지정하기 위해서. 태그는 필요할 경우 변형한다. 이 기본 URL이 포워드 슬래시로 시작하면 서블릿 콘텍스트 이름이 만들어진다. 구체적인 콘텍스트 이름은 context 애트리뷰트를 사용하여 제공될 수 있다. 이 애트리뷰트가 생략되면 현재 서블릿 콘텍스트 이름이 사용된다. 서블릿 콘텍스트 이름이 개발 보다는 전개 시에 결정될 때 유용하다.



isting 12. <c:url> 작동 신택스
<c:url value="expression" context="expression"
    var="name" scope="scope">
  <c:param name="expression" value="expression"/>
  ...
</c:url>

		

URL 재작성은 <c:url> 작동에 의해 자동적으로 수행된다. JSP 컨테이너가 사용자의 현재 세션 아이디를 저장하고 있는 쿠키를 검사하면 재작성은 필요없다. 쿠키가 존재하지 않으면 <c:url>로 만들어진 모든 URL은 재작성되어 세션 아이디를 인코딩한다. 계속되는 요청에도 적절한 쿠키가 존재하지 않으면 <c:url>은 이 아이디를 포함하기 위한 URL 재작성을 멈춘다.

var 애트리뷰트를 위해 값이 제공되면 생성된 URL은 특정 범위 변수의 값으로 할당된다. 그렇지 않다면 결과 URL은 현제 JspWriter를 사용하여 아웃풋이 된다. 결과를 직접 산출하는 기능은 <c:url> 태그가 값으로서 나타날 수 있도록 한다. 예를들어 HTML의 <a> 태그의 href 애트리뷰트와 같다.



Listing 13. HTML 태그용 애트리뷰트 값으로 URL 생성하기
<a href="<c:url value='/content/sitemap.jsp'/>">View sitemap</a>

		

마지막으로 모든 요청 매개변수가 중첩된 <c:param> 태그를 통해 지정되면 그들의 이름과 값은 HTTP GET 요청용 표준 표기법을 사용하여 생성된 URL에 붙여진다. 또한 URL 인코딩이 수행된다. 유효 URL을 만들어내기 위해 변형되어야하는 매개변수의 이름 또는 값에 나타나는 모든 문자는 적절히 변환된다.



Listing 14. 요청 매개변수를 가진 URL 만들기
<c:url value="/content/search.jsp">
  <c:param name="keyword" value="${searchTerm}"/>
  <c:param name="month" value="02/2003"/>
</c:url>

		

Listing 14의 JSP 코드는 blog이라는 이름의 서블릿 콘텍스트에 전개되었다. 범위 변수 searchTerm의 값은 "core library"로 설정되었다. 세션 쿠키가 탐지되면 Listing 14에서 만들어진 URL은 Listing 15와 같다.



Listing 15. 세션 쿠키가 있는 상태에서 만들어진 URL
/blog/content/search.jsp?keyword=foo+bar&month=02%2F2003

		

어떤 세션 쿠키도 없으면 Listing 16의 URL이 그 결과이다. 서블릿 콘텍스트가 프리펜드 되었고 URL 인코딩이된 요청 매개변수가 붙었다.



Listing 16. 세션 쿠키 없이 만들어진 URL
/blog/content/search.jsp;jsessionid=233379C7CD2D0ED2E9F3963906DB4290
  ?keyword=foo+bar&month=02%2F2003
		




위로


중요한 콘텐트

JSP는 두 개의 빌트인 메커니즘을 갖고 있어 다른 URL에서 온 콘텐트를 JSP 페이지로 만든다. 그것이 바로 include 지시문과 <jsp:include> 작동이다. 두 경우 모두, 포함되어야 하는 콘텐트가 페이지로서 같은 웹 애플리케이션의 부분이 되어야 한다. 두 가지 태그의 주요 차이점은 include 지시문은 페이지가 컴파일하는 동안 포함된 콘텐트를 결합하고 <jsp:include> 액션은 JSP 페이지의 요청 프로세스 동안 작동한다는 것이다.

core 라이브러리의 <c:import> 액션은 더욱 일반적이면서 강력한 버전의 <jsp:include>라 할 수 있다. <jsp:include> 처럼, <c:import>는 요청 시간 작동이고 기본 태스크는 다른 웹 리소스의 콘텐트를 JSP 페이지에 삽입하는 것이다.



>Listing 17. <c:import>작동 신택스
<c:import url="expression" context="expression"
    charEncoding="expression" var="name" scope="scope">
  <c:param name="expression" value="expression"/>
  ...
</c:import>

		

임포트 되어야하는 콘텐트용 URL은 url 애트리뷰트를 통해 지정된다. 관련 URL이 허용되고 현재 페이지의 URL에 대비하여 분해된다. url 애트리뷰트의 값은 포워드 슬래시로 시작한다. 하지만 로컬 JSP 컨테이너 내에서는 절대 URL로서 인터프리팅된다. context 애트리뷰트 값 없이는 그와 같은 절대 URL은 현재 서블릿 콘텍스트에서 리소스를 참조하는 것으로 간주된다. 명확한 콘텍스트가 context 애트리뷰트를 통해 지정되면 절대(로컬) URL은 이름을 가진 서블릿 콘텍스트에 대해 분해된다.

<c:import> 액션은 로컬 콘텐트 접근에만 제한되지 않는다. 프로토콜과 호스트 이름을 포함한 전체 URI는 url 애트리뷰트의 값으로 지정될 수 있다. 사실 프로토콜은 HTTP로 제한되지 않는다. java.net.URL 클래스로 지원되는 모든 프로토콜은 <c:import>url 애트리뷰트용 값에서 사용된다. (Listing 18).

<c:import> 액션은 FTP 프로토콜을 통해 액세스 되는 문서의 콘텐트를 포함하는데 사용된다. <c:catch> 액션은 FTP 파일 전송 동안 발생하는 모든 에러를 처리하기 위해 사용된다. <c:catch>var 변수를 사용하여 예외용 범위 변수를 지정하고 <c:if>를 사용하여 값을 검사하면 된다. 예외가 발생하면 범위 변수로의 할당이 발생한다.



Listing 18. <c:import>와 <c:catch>의 결합 예제
<c:catch var="exception">
  <c:import url="ftp://ftp.example.com/package/README"/>
</c:catch>
<c:if test="${not empty exception}">
  Sorry, the remote content is not currently available.
</c:if>
		

<c:import> 액션의 마지막 두 개의 애트리뷰트는 varscope이다. var 애트리뷰트는 지정된 유알엘에서 가져온 콘텐트가 현재의 JSP 페이지에 포함되도록 하는 것이 아니라 변수에 저장되도록 한다. scope 애트리뷰트는 이 변수의 범위 지정을 제어하고 페이지 범위를 초기화한다.




위로


요청 리다이렉션(redirection)

마지막 core 라이브러리 태그는 <c:redirect>이다. 이 액션은 HTTP 리다이렉트 응답을 사용자 브라우저로 보내는데 사용되며, JSTL의 javax.servlet.http.HttpServletResponsesendRedirect() 메소드와 같다. 이 태그의 urlcontext 애트리뷰트 (Listing 19) 작동은 <c:import>urlcontext 애트리뷰트와 같다.



Listing 19. <c:redirect>action
<c:redirect url="expression" context="expression">
  <c:param name="expression" value="expression"/>
  ...
</c:redirect>

		

Listing 20은 <c:redirect> 작동 모습이다. Listing 18의 에러 메시지를 지정된 에러 페이지 리다이렉트로 대체한다. 이 예제에서 <c:redirect> 태그는 표준 <jsp:forward> 작동과 비슷한 방식으로 사용된다. 요청 디스패쳐를 통한 포워딩은 서버쪽에서 구현되지만 리다이렉트는 브라우저에서 수행된다. 개발자의 관점에서 보면 포워딩은 리다이렉팅보다 효율적이다. 하지만 <c:redirect> 액션이 좀더 유연하다. <jsp:forward>는 현재 서블릿 콘텍스트 내에서 다른 JSP 페이지로만 디스패치 할 수 있기 때문이다.



Listing 20. 예외에 대한 응답으로 리다이렉팅
<c:catch var="exception">
  <c:import url="ftp://ftp.example.com/package/README"/>
</c:catch>
<c:if test="${not empty exception}">
  <c:redirect url="/errors/remote.jsp"/>
</c:if>

		

사용자 관점과의 주요 차이점은 리다이렉트가 브라우저로 디스플레이된 URL을 업데이트하고 북마크 설정에 영향을 미친다는 것이다. 반면 포워딩은 엔드유저에게 투명하다. <c:redirect><jsp:forward> 중의 선택은 사용자 경험에 따라 달라진다.




위로


참고자료




위로


필자소개

Mark Kolb는소프트웨어 엔지니어이며 Web Development with JavaServer Pages, 2nd Edition의 공동 저자이다.

:
Posted by 뽀기