14장. 표현 언어와 JSTL - ②JSTL
14.4 커스텀 태그
- 커스텀 태그 : 조건식이나 반복문 등 JSP 페이지에서 자주 쓰이는 자바 코드를 대체하기 위해 만든 태그
- JSTL : JSP 페이지에서 가장 많이 사용하는 기능을 태그로 제공, JSTL 라이브러리로 제공(따로 설치 필요)
- 개발자가 만든 커스텀 태그 : 개발자가 필요에 의해 만든 태그, 스트러츠나 스프링 프레임워크에서 미리 만들어서 제공
14.5 JSP 표준 태그 라이즈러리(JSTL)

- JSTL은 JSP2.0 규약부터 추가된 기능이므로 현재 톰캣에서 기본으로 제공X
사이트에서 라이브러리를 다운로드해야 함
* http://tomcat.apache.org/download-taglibs.cgi
사이트에 접속한 후 Impl, Spec, EL, Compat 네 개의 jar파일을 다운 > lib 폴더에 복사
14.6 Core 태그 라이브러리 사용하기
- 코어 라이브러리로 변수 선언, 조건식, 반복문 기능을 태그로 대체할 수 있음
- (import문 처럼) 코어 태그 라이브러리를 사용하려면 JSP 페이지 상단에 taglib 디렉티브 태그를 추가 해서 톰캣에게 알려줘야 함 : <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
- Core 태그 라이브러리 기능 (<c:태그 ~~> 형태로 사용)
기능 | 태그 | 설명 |
변수지원 | set | JSP 에서 사용될 변수를 설정 |
remove | 설정한 변수를 제거 | |
흐름제어 | if | 조건문 |
choose | switch문, when, otherwise 서브 태그를 가짐 | |
forEach | 반복문 | |
forTokens | 구분자로 분리된 각각의 토큰을 처리 | |
URL 처리 | import | URL을 사용해 다른 자원의 결과를 삽입 |
redirect | 지정한 경로로 redirect (==response.sendRedirect() ) | |
url | URL 재작성 | |
기타 태그 | catch | 예외 처리에 사용 |
out | JspWriter에 내용을 알맞게 처리한 후 출력 |
- 각 태그의 속성에는 표현 언어를 사용할 수 있음
1) <c:set>
- JSP에서 변수를 사용을 위함
- <c:set var="변수이름" value="변수값" [scope="scope속성"] />
일반 변수 ex)
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" import="java.util.*, sec01.ex01.*"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
request.setCharacterEncoding("utf-8");
%>
<c:set var="id" value="hong"/>
<c:set var="pwd" value="1234"/>
<c:set var="name" value="홍길동"/>
<c:set var="age" value="22"/>
<c:set var="height" value="177"/>
<!DOCTYPE html>
...
<tr align="center">
<td>${id}</td> //표현언어로 바로 쓰면 됨
<td>${pwd}</td>
<td>${name}</td>
<td>${age}</td>
<td>${height}</td>
</tr>
contextPath를 변수로 담기 ex)
<c:set var="contextPath" value="${pageContext.request.contextPath}"/>
...
<a href="${contextPath}/test03/memberForm.jsp">회원가입하기</a>
hashMap.ArrayList를 변수로 담기 ex)
<jsp:useBean id="membersList" class="java.util.ArrayList"/>
<jsp:useBean id="membersMap" class="java.util.HashMap"/>
<%
membersMap.put("id","hong");
membersMap.put("pwd","1223");
membersMap.put("name","홍길동");
membersMap.put("email","hong@test.com");
MemberBean m1=new MemberBean("park","1234","박지성","park@test.com");
MemberBean m2=new MemberBean("son","2321","손흥민","son@test.com");
membersList.add(m1);
membersList.add(m2);
membersMap.put("membersList",membersList);
%>
<c:set var="membersList" value="${membersMap.membersList }"/>
..
<tr align="center">
<td>${membersMap.id}</td>
<td>${membersMap.pwd}</td>
<td>${membersMap.name}</td>
<td>${membersMap.email}</td>
</tr>
<tr align="center">
<td>${membersList[0].id}</td>
<td>${membersList[0].pwd}</td>
<td>${membersList[0].name}</td>
<td>${membersList[0].email}</td>
</tr>
<tr align="center">
<td>${membersList[1].id}</td>
<td>${membersList[1].pwd}</td>
<td>${membersList[1].name}</td>
<td>${membersList[1].email}</td>
</tr>
2) <c:remove>
- 변수 제거, 그 삭제된 변수를 표현언어 등으로 접근해도 값은 나오지 않음(화면에는 빈공간)
- <c:remove var="변수이름" [scope=""]/>
3) <c:if>
- <c:if test="${조건식}" var="변수이름" [scope="'] /> </c:if>
- var에는 조건식의 결과(true/false)를 저장
ex)
<c:if test="${true }">
<h1>항상 참입니다.</h1></c:if>
<c:if test="${11==11}">
<h1>두 값은 같습니다</h1></c:if>
<c:if test="${(id=='hong') && (name=='홍길동')}">
<h1>아이디는 ${id }이고 이름은 ${name }입니다.</h1></c:if>
<!-- 조건식의 값은 큰따옴표가 아닌 작은 따옴표로 해야 함 -->
<c:if test="${age==22}">
<h1>${name }의 나이는 ${age }살 입니다.</h1></c:if>
<c:if test="${height>170}">
<h1>${name }의 키는 170보다 큽니다.</h1></c:if>
4) <c:choose>
- == switch문
<c:choose>
<c:when test="조건식1">본문내용1</c:when>
<c:when test="조건식2">본문내용2</c:when>
..
<c:otherwise>본문내용 </c:otherwise>
</c:choose>
ex)
<c:choose>
<c:when test="${empty name }">
<h1>이름을 입력하세요</h1></c:when>
<c:otherwise>
<tr align="center">
<td>${id}</td>
<td>${pwd}</td>
<td>${name}</td>
<td>${age}</td>
<td>${height}</td>
</tr>
</c:otherwise>
</c:choose>
5) <c:forEach>와 <c:forTokens>
- forEach : 반복문
<c:forEach var="변수이름" items="반복할객체이름" begin="시작값" end="마지막값" step="증가값" varStatus="반복상태변수이름"> </c:forEach>
- varStatus의 속성
- index : items에서 정의한 항목을 가리키는 index번호(0부터 시작)
- count : 몇 번째 반복인지 나타냄(1부터 시작)
- first : 첫 번째 반복인지
- last : 마지막 반복인지
- <c:forTokens> var="" items="" delims="구분자" </c:forTokens> >>구분자로 분리된 토큰을 차례로 var에
ex)
<%
List dataList=new ArrayList();
dataList.add("hello");
dataList.add("world");
dataList.add("안녕하세요!");
%>
<c:set var="list" value="<%= dataList %>"/> <!-- 변수 선언 해줘야 함.. ${dataList}로 접근하면 안됐음; -->
...
<c:forEach var="i" begin="1" end="10" step="1" varStatus="loop">
i=${i } 반복횟수 : ${loop.count }<br> </c:forEach> <!-- var 변수를 이용할 때 ${}안에 쓰기 -->
<br>
<c:forEach var="i" begin="1" end="10" step="2">
5 * ${i } = ${5*i }<br></c:forEach> <!-- 변수를 이용한 식을 쓰고 싶으면 ${}한번만 써서 변수 맘대로 쓰면 되는듯 -->
<br>
<c:forEach var="item" items="${list }"> <!-- --> <!-- 선언한 변수 사용이므로 ${list} -->
${ item}<br></c:forEach> <!-- list가 만약 객체 리스트였음 ${item.id}식으로 하면 됨 -->
<br>
<c:set var="fruits" value="사과,파인애플,키위,바나나"/> <!-- 문자열을 토큰으로 분리 -->
<c:forTokens var="fruit" items="${fruits }" delims=",">
${fruit }<br>
</c:forTokens>
6) <c:url>
- URL 정보를 저장하는 역할
- <c:url var="변수이름" value="URL 경로" [scope=""]>
[<c:param var="매개변수이름" value="" />]
</c:url>
- 이 var로 주소에 간편하게 접근하여 href의 값으로 넣는 등 하면 됨
ex)
<c:url var="url1" value="/test01/member1.jsp">
<c:param name="id" value="hong"/>
<c:param name="pwd" value="1234"/>
<c:param name="name" value="홍길동"/>
<c:param name="email" value="hong@test.com"/>
</c:url>
...
<a href="${url1 }">회원정보출력</a>
7) <c:redirect>
- response.sendRedirect()와 같다
<c:redirect url="">
[<c:param name="" value="" />]
</c:redirect>
ex)
<c:redirect url="/test01/member1.jsp">
<c:param name="id" value="hong"/>
<c:param name="pwd" value="1234"/>
<c:param name="name" value="홍길동"/>
<c:param name="email" value="hong@test.com"/>
</c:redirect>
8) <c:out>
- 표현 언어와 기능은 거의 동일
- 기본값 설정 기능 등을 제공하므로 더 편리하게 사용할 수 있음
- <c:out value="출력값" default="기본값" [excapeXml="boolean값"] />
- default속성 : value속성에 지정된 값이 없을 때 출력할 기본 값
escapeXml : excape 문자 변환(기본값 true - 변환 안한다는 말)
ex)
<c:choose>
<c:when test="${empty param.id }">
<h1>아이디를 입력하세요</h1></c:when>
<c:otherwise>
<tr align="center">
<td><c:out value="${param.id}"/></td>
<td><c:out value="${param.pwd}"/></td>
<td><c:out value="${param.name}"/></td>
<td><c:out value="${param.email}"/></td>
</tr>
</c:otherwise>
</c:choose>
- <, >, ' , " 같은 특수 문자를 출력해야 하는 경우 각각의 특수문자에 지정된 문자를 이용해서 브라우저에 출력
- escapeXml을 false로 설정하고 변환된 문자를 입력하면 특수문자가 나온다.
특수문자 | 변환된 문자 |
< | < |
> | > |
& | & |
' | ' |
" | " |
ex)
<c:out value=">" escapeXml="true" />
<c:out value=">" escapeXml="false" />

- 그 외 <c:import>태그는 <jsp:include>와 같은 기능을 수행함
14.7 Core 태그 라이브러리 실습 예제
<c:if test="${not empty param.user_id }">
<c:if test="${param.user_id =='admin'}"> <!-- test="${조건식}" 임에 유의!! -->
<h1>관리자로 로그인 했습니다.</h1>
<form>
<input type="button" value="회원정보 삭제하기"/>
<input type="button" value="회원정보 수정하기"/>
</form>
</c:if>
<c:if test="${param.user_id !='admin'}">
<h1>환영합니다. ${param.user_id }님!!!</h1>
</c:if>
</c:if>
<c:if test="${empty param.user_id }">
아이디를 입력하세요.<br>
<a href=${login }>로그인 창</a></c:if>
- 현재 JSP 페이지는 JSTL로 구현하므로 라이브러리를 사용하는 방법에 익숙해지면 좋음
14.8 다국어 태그 라이브러리 사용하기
- 쇼핑몰 같은 곳에서 언어 변환하는 기능 >> JSP에서 다국어 태그 라이브러리를 사용하는 것
다국어 태그 라이브러리 종류
- 사용하기 위해 <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 를 선언해야 함
태그 | 설명 |
<fmt:setLocale> | Locale(언어)을 지정 |
<fmt:message> | 리소스 번들에서 로케일에 맞는 메시지를 가져와 출력 |
<fmt:bundle> | 사용할 번들 지정 |
<fmt:setBundle> | 리소스번들을 읽어와 특정 변수에 저장 |
<fmt:setParam> | 전달할 매개변수 지정 |
<fmt:requestEncoding> | 요청 매개변수의 문자 인코딩 지정 |
14.9 한글을 아스키 코드로 변환하기
- 다국어 기능을 사용하기 위해선 미리 한글을 아스키 코드로 변환한 형태로 저장하고 있다가 요청 시 이 아스키 코드를 다시 한글로 변환해서 표시. 영어는 변환 필요없이 그냥 영어로 저장하면 됨
<방법>
1. 이클립스에서 한글을 아스키 코드로 변환하는 기능을 제공하는 Properties Editor 플러그인 설치(방법 p.583~586참고)
2. 한글 아스키 파일 만들기
* 프로젝트의 src폴더에 resource패키지 생성
> File 3개 생성(이름 : member.properties, member_en.properties, member_ko.properties)
> member_ko.properties에 키/값 쌍으로 회원 정보를 한글로 작성한 후 저장(작성과 동시에 아스키코드로 변환됨)
member.properties ex)
<!-- member_ko.properties -->
mem.name=\uD64D\uAE38\uB3D9
mem.address=\uC11C\uC6B8\uC2DC \uAC15\uB0A8\uAD6C
mem.job= \uD68C\uACC4\uC0AC
<!-- member_us.properties -->
mem.name = hong-kil-dong
mem.address = kang-nam gu, seoul
mem.job = account
3. JSP 페이지에 다국어 표시하기
ex)
<fmt:setLocale value="en_US"/> <!-- locale을 영어로 지정 -->
<%--<fmt:setLocale value="ko_KR"/>--%>
<!-- locale을 한글로 지정, 둘 중 하나를 택하면 됨 -->
<%--주석 시에 스크립트릿을 사용해야한다!!!ㅠ --%>
<h1>회원정보<br><br>
<fmt:bundle basename="resource.member" >
이름:<fmt:message key="mem.name" /><br>
주소:<fmt:message key="mem.address" /><br>
직업:<fmt:message key="mem.job" />
</fmt:bundle>
</h1>
14.10 포매팅 태그 라이브러리 사용하기
- 원하는 형태로 숫자, 날짜, 문자열을 표시 가능
- 역시 <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 를 선언해야 함
- 포매팅 라이브러리 종류
분류 | 태그 | 설명 |
포매팅 | <fmt:timeZone> | 둘 다 지정한 국가의 시간을 지정하는 태그. 그러나 <fmt:timeZone> 태그의 경우 태그를 열고 닫는 영역 안에서만 적용된다는 차이점을 가지고 있다. |
<fmt:setTimeZone> | ||
<fmt:formatNumber> | 표시할 숫자의 형식을 지정 | |
<fmt:formatDate> | 지정한 형식의 날짜를 표시 |
<formatNumber> 태그의 여러가지 속성
속성 | 설명 |
value | 출력될 숫자를 지정 |
type | 출력된 타입을 지정. percent인 경우 %, number인 경우 숫자, currency인 경우 통화 형식으로 출력 |
dateStyle | 날짜의 출력 형식을 지정 DateFormat 클래스의 full, long, medium, short 등이 지정되어 있음 |
groupingUsed | 콤마(,)등 기호로 구분 여부를 지정 이 속성이 true이면 50000이 50,000으로 표시됨 기본값은 true |
currencyCode | 통화 코드를 지정 한국 원화는 KRW |
currentSimbol | 통화를 표시할 때 사용할 기호를 표시 |
var | <formatNumber>태그 결과를 저장할 변수의 이름을 지정 |
scope | 변수의 접근 범위를 지정 |
pattern | 숫자가 출력될 양식을 지정 자바의 DecimalFormat 클래스에 정의된 형식을 따름 |
- < formatDate> 태그의 여러 속성
속성 | 설명 |
value | 포맷될 날짜를 지정 (ex. value=<%=new Date()%> |
type | 포매팅할 타입을 지정 date인 경우 날짜만, time인 경우 시간만, both인 경우 모두 지정 |
dateStyle / timeStyle |
날짜 / 시간의 출력 형식을 지정 DateFormat 클래스의 full, long, medium, short 등이 지정되어 있음 |
pattern | 직접 출력 형식을 지정 자바 클래스 SimpleDateFormat에 지정된 패턴을 사용 (ex. YYYY-MM-dd hh:mm:ss) |
timeZone | 특정 나라 시간대로 시간을 설정 (ex. <fmt:timeZone value="America/New York">~</fmt:timeZone>) |
~ 여러가지 숫자와 날짜 정보 표시 실습~
<%@ page language="java" contentType="text/html; charset=UTF-8"
import="java.util.Date"
pageEncoding="UTF-8" isELIgnored="false"%>
<%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<% request.setCharacterEncoding("UTF-8"); %>
...
<body>
<h2>formatNumber 예제</h2>
<c:set var="price" value="100000000"/>
<fmt:formatNumber value="${price }" type="number" var="priceNumber"/>
통화로 표현 시: <fmt:formatNumber value="${price }" type="currency" currencySymbol="₩" groupingUsed="true"/><br> <%--통화 표시 특수문자에서 찾아서 해야 함.. --%>
퍼센트로 표현 시 : <fmt:formatNumber value="${price }" type="percent" groupingUsed="false"/><br>
일반 숫자로 표현 시 : "${priceNumber }"<br>
<%--일반 변수로 담았으므로 fmt사용하는게 아니라 바로 표현언어로 변수 값 출력 --%>
<h2>formatDate 예제</h2>
<c:set var="now" value="<%=new Date() %>"/> <%--import java.util.Date해야 함, 한국시간 생성 --%>
<fmt:formatDate value="${now }" type="date" dateStyle="full" /><br>
<fmt:formatDate value="${now }" type="date" dateStyle="short" /><br>
<fmt:formatDate value="${now }" type="time"/><br>
<fmt:formatDate value="${now }" type="both" dateStyle="full" timeStyle="full" /><br>
<fmt:formatDate value="${now }" pattern="YY-MM-DD hh:mm:ss"/><br>
<br><br>
한국 현재 시간:
<fmt:formatDate value="${now }" type="both" timeStyle="full" dateStyle="full"/><br><br>
<fmt:timeZone value="America/New York"> <%-- 표준시간 설정 --%>
뉴욕 현재 시간 : <fmt:formatDate value="${now }" type="both" dateStyle="full" timeStyle="full"/><br>
</fmt:timeZone>
</body>
</html>
14.11 문자열 처리 함수 사용하기
- 자바의 문자열 관련 기능을 JSTL에서 제공하는 함수를 이용해서 JSP에서도 사용할 수 있음
- <%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> 필요
- <JSTL에서 제공하는 문자열 함수>
함수 | 반환 | 설명 |
fn:contains(A,B) | boolean | 문자열 A에 문자열 B가 포함되어 있는지 확인 |
fn:endWith(A,B) | boolean | 문자열 A의 끝이 B로 끝나는지 확인 |
fn:indexOf(A,B) | int | 문자열 A에서 B가 처음으로 위치하는 인덱스를 반환 |
fn:length(A) | int | 문자열 A의 전체 길이를 반환 |
fn:replace(A,B,C) | String | 문자열 A에서 B에 해당되는 문자를 찾아 C로 변환 |
fn:toLowerCase(A) | String | A를 모두 소문자로 변환 |
fn:toUpperCase(A) | String | A를 모두 대문자로 변환 |
fn::substring(A,B,C) | String | A에서 인덱스 번호 B에서 C 앞까지 해당하는 문자열을 반환 |
fn:split(A,B) | String[] | A에서 B에서 지정한 문자열로 나누어 배열로 반환 |
fn:trim(A) | String | 문자열 A에서 앞뒤 공백을 제거 |
ex)
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
...
<c:set var="title1" value="hello world!" />
<c:set var="title2" value="쇼핑몰 중심 JSP입니다!" />
<c:set var="str1" value="중심" />
<h2>여러 가지 문자열 함수 기능</h2>
title1="hello world!"<br>
title2="쇼핑몰 중심 JSP 입니다!"<br>
str1="중심"<br><br>
${fn:length(title1) }<br> //12
${fn:toUpperCase(title1)}<br> //HELLO WORLD!
${fn:toLowerCase(title1)}<br><br> //hello world!
${fn:substring(title1,3,6)}<br> //lo
${fn:trim(title1)}<br>
${fn:replace(title1," ","/")}<br><br> //hello/world!
${fn:indexOf(title2,str1) }<br> //4
${fn:contains(title1,str1) }<br> //false
${fn:contains(title2,str1) } //true
14.12 표현 언어와 JSTL을 이용한 회원 관리 실습
- db와 연동하고 표현언어와 JSTL로 값을 가져오기
- test06/memberList
<c:choose>
<c:when test="${membersList==null }"> <%--바인딩된 속성 이름으로 바로 가져오기 --%>
<tr>
<td colspan=5>
<b>등록된 회원이 없습니다.</b>
</td>
</tr>
</c:when>
<c:otherwise>
<c:forEach var="mem" items="${membersList }">
<tr align="center">
<td>${mem.id}</td>
<td>${mem.pwd}</td>
<td>${mem.name}</td>
<td>${mem.email}</td>
<td>${mem.joinDate}</td>
</tr>
(기타) OracleServiceXE가 수동으로 시작하는 것으로 설정됐으므로 컴퓨터 재부팅 후에는 직접 시작해줘야 한다
