본문으로 건너뛰기
홈
기술
기술 전체
프로그래밍68
컴퓨터 과학63
AI48
웹 개발36
인프라33
데이터31
소프트웨어 공학18
소개
← 목록으로웹 개발 › 프론트엔드 › JSP

[JSP] JSTL

목차

이 글의 표와 URI는 JSTL 1.x 시절의 학습 기록이다. Jakarta Tags 3.0에서는 jakarta.tags.core 같은 새 URI를 사용한다. 아래의 현재 버전 예제와 구분해서 읽는다.

JSTL 다운로드 사이트 : http://tomcat.apache.org/download-taglibs.cgi

JSTL의 기능

  • 간단한 프로그램 로직(자바 변수 선언, if문, for문 등에 해당하는 로직)

  • 다른 JSP 페이지 호출(<c:redirect>, <c:import>)

  • 날짜, 시간, 숫자 포멧

  • JSP 페이지 하나를 가지고 여러가지 언어의 웹 페이지 생성

  • 데이터베이스 입력 수정 삭제 조회

  • xml 문서 처리

  • 문자열 처리함수 호출

 커스텀 태그 

 prefix

 기본 URI 

 설명 

 기본기능(core)

 c

http://java.sun.com/jsp/jstl/core 

  일반 프로그램이 언어에서 제공하는 것과 유사한 변수 선언, 실행 흐름의 제어 기능을 제공하고, 다른 JSP 페이지로 제어를 이동하는 기능을 제공

 형식화(format)

 fmt

http://java.sun.com/jsp/jstl/fmt

  숫자, 날짜 시간, 굿제화, 다국어 지원 기능제공

 데이터베이스(sql)

 sql

http://java.sun.com/jsp/jstl/sql

  데이터베이스의 데이터 입력/수정/삭제/조회 기능을 제공

 XML 처리(xml)

 x

http://java.sun.com/jsp/jstl/xml

  XML문서를 처리할 때 필요한 기능을 제공

함수처리(functions) 

 fn

http://java.sun.com/jsp/jstl/fn

  문자열을 처리하는 함수 제공

<커스텀 태그>

1. Core 태그

태그 

 설명 

 <c:set>

 변수 값을 설정 

 <c:remove>

 변수에 설정된 값을 제거

 <c:if>

  조건을 처리할 때 사용 (if문)

 <c:choose>

  여러 조건에 따라 처리를 할 때 사용 

 <c:forEach>

  반복 처리를 할 때 사용

 <c:forTokens>

  구분자로 분리된 각각의 토큰을 처리할 때 사용

 <c:import>

  외부의 url을 지정하여 가져다 사용

 <c:redirect>

 지정한 경로로 이동

 <c:url>

  url을 재작성

 <c:out>

 html내에 데이터를 화면에 출력 <%=%> 와 같은 기능

 <c:catch>

 예외처리

<c:set>

  • var 속성에는 문자열 형태로 변수의 이름을 설정하고 value에는 지정할 값을 설정한다. scope는 생략되어있으면 기본값은 page로 설정된다.
<c:set var="변수이름" value="저장할 값" scope="{page|request|session|application}"/>

<c:set var="name" value="hello" scope="page"/>
(pageContext.setAttribute("name"hello");) 와 같다.

OR

<c:set var="변수이름" scope="{page|request|session|application}">
변수에 저장할 값
</c:set>

<c:set var="age" scope="page">
30
</c:set>

<c:remove>

- removeAttribute()와 같은 역할이다. 변수를 제거하는 역할을 한다.

<c:remove var="변수이름" scope="{page|request|session|application}"/>

<c:remove var="age"/>

<c:if>

자바의 if문과 비슷한 기능을 한다.

<c:if test="조건식">
조건이 참일경우 실행할 문장
</c:if>

<c:choose>

-<c:if>태그는 else 문을사용할 수 없기 때문에 else if 문구문을 사용하려면 <c:choose>를 이용하여야한다.

<c:choose>내에 여러개의 <c:when> 을 가질 수 있고 순서대로 test조건을 검사하여 결과가 참이면 <c:when>구문태그를 실행한다

조건을 찾지 못할 경우 <c:otherwise>을 실행한다. 생략도 가능.

<c:choose>
<c:when test="조건1"> 결과 </c:when> 
<c:when test="조건2"> 결과 </c:when>
<c:otherwise> 결과 </c:otherwise>
</c:choose>

<c:forEach>

  • array나 컬렉션 또는 맵 같은 집합체에 저장되어 있는 값들을 순차적으로 처리할 때 사용할 수 있는 태그
<c:forEach var="변수이름" items="배열과 같은 집합체">
처리할 내용
</c:forEach>

- varStatus

배열이나 컬렉션 집합체에서 항목의 인덱스 값을 사용할 때 반복상태 관련 정보를 알려줌

 프로퍼티

 설명 

 index 

items에 지정한 집합체의 현재 반복중인 항목의 index를 알려준다 0부터 순서가 부여됨

 count 

 루핑을 돌 때 현재 몇 번째를 반복 중인지 알려준다. 1부터 순서가 부여됨.

 first

 현재 루프가 처음인지 여부를 알려준다. 첫 번째 일경우 true 아니면 false를 리턴

 last 현재 루프가 마지막인지 여부를 알려준다. 마지막일 경우 true 아니면 false를 리턴 
<c:forEach var="movie" items="${movieList}" varStatus="status"> //반복상태 정보를 위한 변수
${status.count} ${status.index}	${movie}<br>

</c:forEach>

- begin, end 속성

begin, end속성을 이용하여 시작번호와 끝 번호를 지정하고 step 속성을 이용하여 증가 구간을 설정하여 원하는 만큼 반복을 수행 할 수 있다.

//varStatus를 이요하여 줄수도 있음
<c:forEach [var="변수이름"] begin="시작 값" end="끝값" [step="증가치"]></c:forEach>

ex)
step를 지정하여 2씩증가
<c:forEach var="i" begin="1" end="10" step="2">
${i} &nbsp;
</c:forEach>

1부터 10까지 증가
<c:forEach var="i" begin="1" end="10" varStatus="status">
${i} &nbsp; ${status.index} &nbsp; ${status.count} <br>
</c:forEach>

<c:forTokens>

  • java.util.StringTokenizer와 같이 문자열을 구분자로 분리해서 하나씩 추출할 수 있는 태그 기능
<c:forTokens var="토큰을 저장할 변수" items="토큰을 나눌 문자열" delims="구분자">
처리내용
</c:forTokens>

ex)
<c:forTokens var="city" items="서울,대전,대구,부산.인천,동해" delims=",">
${city}<br>

</c:forTokens>

<c:import>

  • 다른 페이지의 내용을 변수에 저장하여 내용을 동적으로 포함시켜 사용하는 것.
<c:import url="URL" [var="변수이름"] [scope="영역"] [charEncoding="charEncoding"]>
</c:import>
${변수명}

<c:url>

  • 여러번 반복 할 주소가 있다면 변수에 저장하여 사용
<c:url value="URL" [var="변수명"] [scope="영역"]></c:url>
${변수명}

<c:redirect>

  • response.sendRedirect() 메소드와 동일한 기능을 제공한다. 지정한 페이지로 이동시키기 위해 사용
<c:redirect url="URL" [context="경로명"]></c:redirect>

<c:out>

  • value 속성에 지정한 문자열 혹은 변수의 내용을 출력할 때 사용하는 태그로써 <%=%>와 같은 역할을 함.
<c:out value="출력할 값" [default="기본값"]>

value : 출력할 값 지정
default : 지정한 값이 없을 경우 사용할 값을 지정

<c:catch>

  • 예외 처리를 하기 위해서 사용하는 태그
<c:catch var="변수이름"> 
예외가 발생할 수 있는 코드
</c:catch>

<c:catch var="errmsg">
 예외발생전
 <%=1/0 %>
예외발생후
</c:catch>
<c:out value="${errmsg}"></c:out>

2. fml 태그

국제화 지역화 태그로 jsp에서 다양한 언어를 지원받을 수 있도록 할 수 있고, 날짜와 숫자 형식을 다루는데 사용함.

기능 

 태그

 설명

 숫자 날짜 형식

  formatNumber

  숫자를 양식에 맞춰서 출력 

  formatDate

  날짜 정보를 담고 있는 객체를 포멧하여 출력할 때 사용 

  parseDate

  문자열을 날짜로 변경한다.

  parseNumber

  문자열울 숫자로 변경한다.

  setTimeZone

  시간대별로 시간을 처리할 수 있는 기능을 설정

  timeZone

  시간대별로 시간을 처리할 수 있는 기능을 제공한다.

Locale 지정 

  setLocale

  국제화 태그들이 사용할 Locale을 지정한다

  requestEncoding

  요청 파라미터의 인코딩을 지정

 메시지 처리

  bundle

  태그 몸체에서 사용할 리소스 번들을 지정

  message(param)

  메시지를 출력

  setBundle  특정 리소스 번들을 사용할 수 있도록 로딩

<fmt:formatNumber>

수치 데이터는 숫자, 통화량, 퍼센트등을 표현하는 형식으로 원하는 형식으로 수치 데이터를 표현하기 위한 태그

<fmt:formatNumber value="수치데이터" [type="{number | currency | percent}"] [pattern="패턴"] 
  [currencySymbol="화폐단위"]  [groupingUsed= "{true | false}"] [var="변수 이름"] 
  [scope="{page | request | session | application}"]>

<fmt:formatDate>

날짜와 시각 등 형식들을 표현하는 태그

Jakarta Tags 3.0에서 목록을 렌더링하기

현재 Jakarta EE 계열 프로젝트에서 사용한다면 Servlet·Pages·Tags API의 호환 버전을 먼저 맞춘다. Jakarta Tags 3.0의 core URI는 jakarta.tags.core다. 과거 http://java.sun.com/jsp/jstl/core URI도 사양상 허용되지만, 새로운 코드에서는 의존성과 태그 URI를 한 세대로 통일하는 편이 혼동이 적다.

게시글 목록을 예로 들어보자. 서블릿이 저장소에서 목록을 읽어 요청 속성에 넣고, JSP는 출력만 담당한다.

List<PostSummary> posts = postService.listRecent();
request.setAttribute("posts", posts);
request.getRequestDispatcher("/WEB-INF/views/posts.jsp")
       .forward(request, response);

PostSummary는 id, title을 가진 화면용 데이터 타입이라고 가정한다. /WEB-INF 아래 JSP는 브라우저가 직접 URL로 호출하는 대신 서블릿을 통해 렌더링한다. SQL을 JSP의 <sql:query> 태그에 넣는 방식은 표현과 데이터 접근을 섞어 테스트·권한 검사·트랜잭션 관리를 어렵게 한다.

<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<ul>
  <c:forEach var="post" items="${posts}">
    <li>
      <c:url var="detailUrl" value="/posts/${post.id}" />
      <a href="${detailUrl}"><c:out value="${post.title}" /></a>
    </li>
  </c:forEach>
</ul>
<c:if test="${empty posts}">
  <p>게시글이 없습니다.</p>
</c:if>

<c:forEach>는 목록을 순회한다. <c:out>는 기본적으로 XML 특수 문자를 이스케이프해 제목에 <script>처럼 보이는 문자열이 있어도 HTML 요소로 해석되지 않게 한다. 그러나 href 같은 속성·URL 문맥의 안전성은 별도 검토가 필요하다. 위 예시는 ID가 서버가 만든 숫자 식별자라는 전제다. 임의의 URL을 사용자에게 받는다면 허용 스킴과 경로를 검증한다.

flowchart LR
  A["GET /posts"] --> B["Servlet"]
  B --> C["서비스·저장소에서 조회"]
  C --> D["request 속성 posts"]
  D --> E["JSP의 c:forEach"]
  E --> F["c:out으로 제목 출력"]

request 속성은 현재 요청의 렌더링에만 필요하다. 같은 목록을 session에 저장하면 다른 요청에서도 남아 최신 데이터와 어긋나고 메모리를 차지할 수 있다. 언어 선택 같은 작은 사용자별 상태와 목록 데이터는 수명이 다르다.

조건·반복이 예상과 다를 때

증상확인할 부분
태그가 텍스트로 보임Tags 구현 의존성과 URI, JSP 컨테이너
목록이 비어 보임서블릿 속성 이름과 JSP의 EL 이름
제목에 HTML이 실행됨c:out 사용 여부와 출력 문맥
링크가 잘못됨애플리케이션 context path와 c:url
조건 분기가 겹침독립 c:if 대신 c:choose 필요 여부

<c:import>에 사용자 제공 URL을 바로 넣으면 서버가 임의의 주소에 요청할 수 있다. 외부 URL을 가져오는 기능은 서버 측 허용 목록과 네트워크 정책을 거쳐야 한다. <c:catch>로 오류를 잡아 화면에서 숨기는 것도 원인 조사에 방해될 수 있다. 실제 업무 실패는 서블릿·서비스에서 처리하고, JSP에는 렌더링에 필요한 상태만 전달한다.

참고: Jakarta Tags 3.0 개요, core 태그 URI와 목록, c:out 문서.

같은 카테고리의 글