참조 : Developing Custom Tag Libraries as Tag Files

1. JSP 조각 태그 파일로 넘겨주기
- attribute의 fragment 사용하면 돼.

<%@ page contentType="text/html" %>
<%@ taglib prefix="my" tagdir="/WEB-INF/tags/mytags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Even and Odd Rows</title>
</head>
<body bgcolor="white">
<h1>Even and Odd Rows</h1>
<table>
<my:forEvenAndOdd items="a,b,c,d,e">
<jsp:attribute name="even">
<c:set var="counter" value="${counter + 1}" />
<tr bgcolor="red"><td>${counter}: Even Row</td></tr>
</jsp:attribute>
<jsp:attribute name="odd">
<c:set var="counter" value="${counter + 1}" />
<tr bgcolor="blue"><td>${counter}: Odd Row</td></tr>
</jsp:attribute>
</my:forEvenAndOdd>
</table>
</body>
</html>

이런 HTML이 있을 때 even이랑 odd라는 JSP 조각을 forEvenAdnOdd 태그 파일로 넘긴다. 물론 items라는 속성도 가지고 있다.

<%@ tag body-content="empty" %>
<%@ attribute name="items" rtexprvalue="true" required="true" %>
<%@ attribute name="even" fragment="true" required="true" %>
<%@ attribute name="odd" fragment="true" required="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<c:forEach items="${items}" varStatus="status">
<c:choose>
<c:when test="${status.count % 2 == 0}">
<jsp:invoke fragment="even" />
</c:when>
<c:otherwise>
<jsp:invoke fragment="odd" />
</c:otherwise>
</c:choose>
</c:forEach> 

태그 파일 안에서 <jsp:invoke>를 사용해서 해당 조각들을 호출할 수 있다. items 속성의 값을 , 로 구분된 리스트로 인식하려고 한 듯, 기본값도 true니까 굳이 적어주지 않아도 될 듯. fragment="true" 는 반드시 설정해 주어야 함. 기본값이 false니까.

JSP에서 태그 파일에서 사용하는 값도 알아야 할 필요가 있다. 위와 같은 경우 태그 타일 내부에서는 a, b, c, d, e를 구분하여 하나씩 값으로 처리하고 있는데 이걸 JSP에서는 모르니까.. JSP로 넘겨주어야 한다. 이럴 때 variable 지시자를 사용한다.

<%@ tag body-content="empty" %>
<%@ attribute name="items" rtexprvalue="true" required="true" %>
<%@ attribute name="even" fragment="true" required="true" %>
<%@ attribute name="odd" fragment="true" required="true" %>
<%@ variable name-given="current" variable-class="java.lang.Object"
scope="NESTED" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:forEach items="${items}" varStatus="status" var="current">
<c:choose>
<c:when test="${status.count % 2 == 0}">
<jsp:invoke fragment="even" />
</c:when>
<c:otherwise>
<jsp:invoke fragment="odd" />
</c:otherwise>
</c:choose>
</c:forEach> 

나머지 부분은 동일하고, current라는 변수를 루프 돌 때 사용하고 있다, 그러면 이제 JSP에서도 current라는 변수로 태그 파일에서 사용하고 있는 값을 참조할 수 있다.

<%@ page contentType="text/html" %>
<%@ taglib prefix="my" tagdir="/WEB-INF/tags/mytags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Even and Odd Rows</title>
</head>
<body bgcolor="white">
<h1>Even and Odd Rows</h1>
<table>
<my:forEvenAndOdd2 items="a,b,c,d,e">
<jsp:attribute name="even">
<c:set var="counter" value="${counter + 1}" />
<tr bgcolor="red"><td>${counter}: Even Row: ${current}</td></tr>
</jsp:attribute>
<jsp:attribute name="odd">
<c:set var="counter" value="${counter + 1}" />
<tr bgcolor="blue"><td>${counter}: Odd Row: ${current}</td></tr>
</jsp:attribute>
</my:forEvenAndOdd2>
</table>
</body>
</html>

 
그런데, JSP 입장에서 보면 참 쌩뚱 맞을 수 밖에 없다. 느닺없이 current라는 변수가 튀어 나왔다. 도대체 어디서 튀어 나온 녀석이냐며 심각한 고민에 빠질 수도 있다. 그래서 태그의 속성으로 current라는 이름을 리스트의 인자를 가리킬 때 사용할 거라는 것을 알려줘야 한다.

<%@ tag body-content="empty" %>
<%@ attribute name="items" rtexprvalue="true" required="true" %>
<%@ attribute name="var" rtexprvalue="false" required="true" %>
<%@ attribute name="even" fragment="true" required="true" %>
<%@ attribute name="odd" fragment="true" required="true" %>
<%@ variable name-from-attribute="var" alias="current"
variable-class="java.lang.Object" scope="NESTED" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:forEach items="${items}" varStatus="status" var="current">
<c:choose>
<c:when test="${status.count % 2 == 0}">
<jsp:invoke fragment="even" />
</c:when>
<c:otherwise>
<jsp:invoke fragment="odd" />
</c:otherwise>
</c:choose>
</c:forEach>

이전 태그 파일과 다른 부분은 name-given 대신에 name-from-attibute를 사용했고, 그 값으로 var라는 attribute를 지정했다. 이 속성은 rtexprvalue를 false로 지정해두었다. 무슨 값이 오던 신경끄라는 것 같다. 그냥 그 값으로 태그 파일 내부의 값을 참조하게 된다. 안에서 보면 좀 어지럽지만.. 밖에서 보면 간단해진다.

<%@ page contentType="text/html" %>
<%@ taglib prefix="my" tagdir="/WEB-INF/tags/mytags" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>Even and Odd Rows</title>
</head>
<body bgcolor="white">
<h1>Even and Odd Rows</h1>
<table>
<my:forEvenAndOdd3 items="a,b,c,d,e" var="anyName">
<jsp:attribute name="even">
<c:set var="counter" value="${counter + 1}" />
<tr bgcolor="red"><td>${counter}: Even Row: ${anyName}</td></tr>
</jsp:attribute>
<jsp:attribute name="odd">
<c:set var="counter" value="${counter + 1}" />
<tr bgcolor="blue"><td>${counter}: Odd Row: ${anyName}</td></tr>
</jsp:attribute>
</my:forEvenAndOdd3>
</table>
</body>
</html> 

멋지다. 이제 더 이상 current라는 변수 명이 어디서 왔는지 신경쓰지 않아도 되고, 거기에 얽매이지 않아도 된다. 원하는 이름으로 태그 파일에 주고 그 이름으로 태그 파일에 있는 값을 가져올 수 있다.

이렇게 진화하는 예제를 가지고 글을 써주는 사람들은 정말 멋진 것 같다. 머리에도 잘 들어오고, 이해하기도 좋은 것 같다. Good!!