[JSP] JSTL
JSTL(JSP Standard Tag Library)은 JSP에서 사용 가능한 표준 태그들을 모아놓은 라이브러리로, JSP 페이지에서 java 코드를 바로 사용하지 않도록 이를 HTML 태그 형태로 만들어 제공한다. 이 JSTL은 자바 코드 로직을 포장해놓은 개념이기에 장황하게 자바 코드를 JSP에서 작성하지 않아도 되어 코드의 간결성을 확보할 수 있으며, HTML 태그와 똑같은 형태를 지니기에 HTML과 조화를 이룰 수 있어 가독성도 챙길 수 있다.
JSTL 설치
JSTL을 사용하려면 우선 JSTL jar 파일을 다운로드 받아 프로젝트 폴더에 등록시켜야 한다. 다음의 사이트에서 jar 파일을 다운로드 받는다.
Maven Repository: javax.servlet » jstl » 1.2
위 사진처럼 “jar” 파일을 다운로드 받으면 된다.
“jstl-1.2.jar”라는 파일을 웹 프로젝트 폴더의 WEB-INF/lib 폴더 내에 위치시킨 후 이를 해당 프로젝트 폴더에 “build path”를 통해 등록시키면 된다. 그러면 설치가 완료되어 JSTL을 사용할 수 있게 된다.
참고로, 톰캣 폴더의 webapps\examples\WEB-INF\lib
폴더 내부에는 taglibs-standard-impl-1.2.5.jar
파일과 taglibs-standard-spec-1.2.5.jar
파일이 있는데 이 두 파일을 복사하여 가져다 사용해도 된다.
JSTL 태그 종류
JSTL에는 여러 종류의 태그 라이브러리가 있는데 다음과 같다.
JSTL tag | prefix | uri | 설명 |
---|---|---|---|
Core | c | http://java.sun.com/jsp/jstl/core | 변수 선언, 조건문, 반복문 등의 실행 흐름 제어 기능 제공. URL 관련 기능 및 페이지 이동 등의 여러 기능들을 제공. |
xml | x | http://java.sun.com/jsp/jstl/xml | XML 파일 처리에 사용되는 태그들의 모임. |
fmt | fmt | http://java.sun.com/jsp/jstl/fmt | 날짜, 숫자, 문자 데이터 포맷을 지정하는 기능 제공. |
SQL (DB) | sql | http://java.sun.com/jsp/jstl/sql | DB 연동 관련 기능 제공. |
Functions | fn | http://java.sun.com/jsp/jstl/functions | 문자열 관련 함수들을 제공한다. |
여기서 사실상 자주 쓰이는 태그들은 Core와 fmt이라고 한다.
JSTL 사용을 위한 taglib directive
JSP 페이지 내에서 JSTL 사용을 위해서는 우선 코드 상단에 <%@ taglib %>
라는 지시자를 선언해야 한다. 해당 지시자에는 prefix와 uri 속성이 들어간다. 이 둘의 속성은 앞선 표의 값을 사용하면 된다. 예를 들어 Core 태그를 사용하고자 한다면 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
와 같이 선언하면 된다.
다음 예제 코드를 보면 taglib 지시자를 어떻게 사용하는지 알 수 있을 것이다.
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:set var="num" value="1"></c:set>
${ num }
</body>
</html>
jstlTest.jsp
위 파일을 톰캣 서버에서 실행 시 위와 같이 브라우저 화면에 숫자가 뜬다면 JSTL을 사용할 수 있다는 뜻이다.
이제 몇몇 태그 라이브러리들에 대해 살펴보겠다.
Core
<c:set>
<c:set var="변수명" value="값" />
태그는 변수를 선언하고 값을 초기화하는 데 쓰이는 태그이다.
다은은 해당 태그를 이용하여 변수 선언 및 정수값 초기화를 한 후 각각의 변수들을 출력하고 총합도 출력하는 예제이다.
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:set var="num1" value="10"/>
<p>${ num1 }</p>
<c:set var="num2" value="20"></c:set>
<p>${ num2 }</p>
<c:set var="total" value="${ num1 + num2 }" />
<p>${ total }</p>
</body>
</html>
coreSet.jsp
위 예제와 결과를 보면 알겠지만, JSTL 태그 속성값으로 EL과 같이 사용될 수 있음을 알 수 있다. 보통 EL과 JSTL가 함께 사용된다고 한다.
한 편, <c:set>
태그에는 scope 속성도 사용할 수 있으며, 이전에 EL에서 접한 page, request, session, application context 객체들 중 하나를 값으로 넣을 수 있다. 이 속성을 생략하면 “page”로 설정된다. 다음은 이를 확인하는 예제이다.
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<c:set var="num1" value="10"/>
<p>${ num1 }</p>
<c:set var="num2" value="20"></c:set>
<p>${ num2 }</p>
<c:set var="total" value="${ num1 + num2 }" />
<p>${ total }</p>
<!-- scope 속성 테스트. -->
<c:set var="wow" value="빡빡이 친구들!"/>
<c:set var="bow" value="월월!" scope="session" />
<a href="coreSetScope.jsp">Go to other page</a>
</body>
</html>
coreSet.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<p>${ wow }</p>
<p>${ bow }</p>
</body>
</html>
coreSetScope.jsp
coreSet.jsp를 브라우저 상에서 실행하면 다음의 결과를 얻는다.
scope 속성 생략 시 해당 변수의 scope는 기본적으로 page로 설정되기에 다른 jsp 페이지에서 해당 변수값을 가져올 수 없다. 반면 scope=”session”이라고 하면 해당 변수값은 session context 내부에 저장되기에 다른 페이지에서도 해당 데이터를 가져다 사용할 수 있는 것이다.
조건문 태그
JSTL의 Core 태그 라이브러리에는 조건문으로 <c:if>
와 <c:choose>
태그가 존재한다. 전자는 자바의 if문과 동일하게 사용 가능하며, 후자는 자바의 switch와 동일하다.
<c:if>
해당 태그에는 test라는 속성이 있는데 이 속성값으로 boolean 자료형 값을 반환하는 조건문을 넣을 수 있다. 조건문 삽입을 위해 EL과 같이 사용된다. test 속성값에 명시된 조건문이 true이면 해당 if 태그 내부에 HTML 태그를 삽입하여 화면에 어떠한 결과를 출력하게 할 수 있다. 다음은 해당 조건문 태그를 사용하는 예제이다.
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form>
<p>정수 입력: <input type="number" name="integer" /></p>
<input type="submit" value="입력" />
</form>
<c:if test="${!empty param.integer }">
<c:if test="${ param.integer % 2 == 0 }">
<p>입력하신 ${ param.integer }이란 숫자는 짝수입니다.</p>
</c:if>
<c:if test="${ param.integer % 2 != 0 }">
<p>입력하신 ${ param.integer }이란 숫자는 홀수입니다.</p>
</c:if>
</c:if>
</body>
</html>
coreIf.jsp
JSTL에는 else 문에 해당하는 태그가 없다고 한다. 그래서 else 관련 태그 없이 오로지 <c:if>
문으로만 조건문을 사용해야 한다. 아니면 다음에 소개할 태그를 쓰든가 해야 한다.
<c:choose>
<c:choose>
태그는 자바의 switch와 같다. 그래서 해당 태그의 자식 태그로써 같이 사용되는 태그가 있다.
<c:when test="${ 조건식 }"> (화면 출력용 HTML 태그들) </c:when>
: switch문의 case과도 같다.<c:otherwise> (화면 출력용 HTML 태그들) </c:otherwise>
: switch문의 default과 같다.
다음은 앞선 홀짝 판별 문제를 <c:choose>
태그로 푸는 예제이다.
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form>
<p>정수 입력: <input type="number" name="integer" /></p>
<input type="submit" value="입력" />
</form>
<c:if test="${!empty param.integer }">
<c:choose>
<c:when test="${ param.integer % 2 == 0 }">
<p>입력하신 ${ param.integer }이란 숫자는 짝수입니다.</p>
</c:when>
<c:otherwise>
<p>입력하신 ${ param.integer }이란 숫자는 홀수입니다.</p>
</c:otherwise>
</c:choose>
</c:if>
</body>
</html>
coreChoose.jsp
결과는 앞선 coreIf.jsp와 같다.
반복문 태그
<c:forEach>
태그는 자바에서의 for문과 동일한 기능을 한다. 자바에서는 카운터 변수(i)를 이용한 방법과 enhanced for문 이 두 방식이 있듯, 해당 태그도 두 가지 방식으로 사용할 수 있다.
카운터 변수를 이용하여 반복문을 사용하려면 다음의 속성들이 사용된다.
<c:forEach begin="시작숫자" end="끝숫자" step="증감" var="카운터 변수">
반면 enhanced for문 형식으로 사용하려면 다음과 같이 사용할 수 있다.
<c:forEach var="아이템" items="아이템들">
다음은 두 방식 모두 이용하여 사용자가 좋아하는 음식들을 입력하면 그 음식들을 그대로 출력하는 예제이다.
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h3>좋아하는 음식 선택 (다중 선택 가능)</h3>
<form>
<ul>
<li>
<label for="pizza">피자</label>
<input type="checkbox" name="food" value="피자" id="pizza" />
</li>
<li>
<label for="hamburger">햄버거</label>
<input type="checkbox" name="food" value="햄버거" id="hamburger" />
</li>
<li>
<label for="samgupsal">삼겹살</label>
<input type="checkbox" name="food" value="삼겹살" id="samgupsal" />
</li>
<li>
<label for="gukbab">국밥</label>
<input type="checkbox" name="food" value="국밥" id="gukbab" />
</li>
<li>
<label for="zzolmeon">쫄면</label>
<input type="checkbox" name="food" value="쫄면" id="zzolmeon" />
</li>
</ul>
<input type="submit" value="제출" />
</form>
<hr/>
<!-- 일반적인 for문 방식 -->
<c:if test="${!empty paramValues.food }">
<h2>당신이 선택한 음식들</h2>
<ul>
<c:forEach begin="0" end="5" step="1" var="i">
<c:if test="${!empty paramValues.food[i] }">
<li>${ paramValues.food[i] }</li>
</c:if>
</c:forEach>
</ul>
</c:if>
<hr/>
<!-- Enhanced for문 방식 -->
<c:if test="${!empty paramValues.food }">
<ul>
<c:forEach var="oneFood" items="${ paramValues.food }">
<li>${ oneFood }</li>
</c:forEach>
</ul>
</c:if>
</body>
</html>
coreForEach.jsp
한편, <c:forTokens items="아이템들" delims="구분자" var="토큰변수">
태그도 있는데, 이는 for문과 StringTokenizer가 결합한 기능의 태그라 보면 된다. 다음은 이를 활용한 예제이다.
<%@page import="java.util.StringTokenizer"%>
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<form method="post">
<select name="book">
<option value="default">
선택
</option>
<option value="코딩 잘하는법/김큐엘/23000원">
코딩잘하는법/김큐엘/23000원
</option>
<option value="날계란과 삶은 계란 구분법/정디비/8000원">
날계란과 삶은 계란 구분법/정디비/8000원
</option>
<option value="맨홀 뚜껑이 정사각형이 아닌 원 형태인 이유/자바스/7000원">
맨홀 뚜껑이 정사각형이 아닌 원 형태인 이유/자바스/7000원
</option>
</select>
<input type="submit" value="구매" />
</form>
<% request.setCharacterEncoding("utf-8"); %>
<table border="1">
<tr>
<th>제목</th>
<th>저자</th>
<th>가격</th>
</tr>
<c:if test="${!empty param.book and param.book ne 'default' }">
<tr>
<c:forTokens items="${ param.book }" delims="/" var="token">
<td>${ token }</td>
</c:forTokens>
</tr>
</c:if>
</table>
<hr/>
<!-- script tag 방식 -->
<table border="1">
<tr>
<th>제목</th>
<th>저자</th>
<th>가격</th>
</tr>
<%
String bookInfo = request.getParameter("book");
if (bookInfo != null && !bookInfo.equals("default")) {
%>
<tr>
<%
StringTokenizer tokens = new StringTokenizer(bookInfo, "/");
while(tokens.hasMoreTokens()) {
%>
<td><%= tokens.nextToken() %></td>
<%
}
%>
</tr>
<%
}
%>
</table>
</body>
</html>
coreForTokens.jsp
페이지 이동
JSTL에서는 redirect 방식의 페이지 이동을 할 수 있는 태그를 지원하는데, <c:redirect url="new url">
태그를 이용한다. 해당 태그의 자식 태그로 <c:param name="name" value="value">
를 사용할 수 있는데, 새 페이지로 이동 시 요청 파라미터로 전달할 name-value 쌍 데이터를 지정할 수 있다. 다음은 이를 활용한 예제이다.
<%@ page contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<p>로그인</p>
<form method="post">
<p>닉네임: <input type="text" name="nickname" /></p>
<p>이메일: <input type="email" name="email" /></p>
<input type="submit" value="로그인"/>
</form>
<% request.setCharacterEncoding("utf-8"); %>
<c:if test="${!empty param.nickname and !empty param.email }">
<c:redirect url="coreRedirectDest.jsp">
<c:param name="nickname" value="${ param.nickname }"></c:param>
<c:param name="email" value="${ param.email }"></c:param>
</c:redirect>
</c:if>
</body>
</html>
coreRedirect.jsp
<%@ page contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<p>${ param.nickname }님, 환영합니다.</p>
<p>${ param.nickname }님의 이메일: ${ param.email }</p>
</body>
</html>
coreRedirectDest.jsp
References
[1] 에이콘아카데미(강남) 강의
[2] 채규태, “채쌤의 Servlet&JSP 프로그래밍 핵심”, (쌤즈, 2023)
[3] TLD 문서
TLDDoc Generated Documentation
[4] JSTL 관련 튜토리얼
JavaServer Pages Standard Tag Library
[5] [JSP] JSTL 개념 및 장점, 설치/사용방법 소개
This content is licensed under
CC BY-NC 4.0
댓글남기기