[Java] 42. Web Spring framework의 view에서 사용하는 언어(JSTL) - 코어, 포멧팅


Study/Java  2021. 6. 7. 15:53

안녕하세요. 명월입니다.


이 글은 Web Spring framework의 view에서 사용하는 언어(JSTL) - 코어, 포멧팅에 대한 글입니다.


먼저 JSTL은 JSP Standard Tag Library의 약어로서 JSP 웹 페이지에 사용되는 태그 형식의 프로그래밍 언어입니다. 이 언어는 Spring에서만 사용되는 것이 아니라 예전의 Servlet이나 Struts(스트럿츠) 프레임 워크에서도 사용되었습니다.

이게 예전에 개발자와 웹 디자이너의 업무를 분담하던 당시에 웹 디자이너들이 프로그램 언어가 익숙하지는 않고 배우기 힘들다고 해서 사용된 디자이너 전용 언어라는 속설(?)이 있었습니다. 솔직히 이게 진짜인지는 잘 모르겠습니다만...

확실히 Java 프로그래밍 언어보다는 쉽고 간단한 언어인 것은 확실합니다.


그리고 프로젝트 안에서 작성된 프로그램 언어와 종속된 개념이 아니기 때문에 Controller단과 View단, 즉 Front-end와 Back-end와 확실히 구분되어 개발이 가능합니다.

이건 솔직히 프로젝트 공정에 대한 개념이긴 합니다만,Back-end는 DB(데이터베이스)와 서버 환경설정이나 서버 구성을 담당하고 Front-end는 화면 쪽은 css와 javascript의 언어를 사용해서 프로그래밍을 하는 것을 말합니다.


근데 이게 예전에 그랬다고는 하는데 저는 그렇게 구분해서 개발한 적이 없었던 것 같네요.

저는 개발 신입때는 웹 디자이너들에게 이미지등을 따서 넘겨 받으면 css 변환하고 그에 맞게 javascript를 작성하고 그 후에는 ajax 개념이 생겨서 거의 data는 ajax로 처라하는 식으로 개발하곤 했습니다.

그러다 이후에 Bootstrap 등이 생겨서 개발자에 맞는 화면 개발법이나 공정에 대한 개념이 생긴 후에는 화면부터 납품까지 거의 개발자가 다 했던 것같네요.. 어느 순간 웹 디자이너 직종이 없어진 듯한.. 단순한 저의 경험일 뿐이니 일반화는 아닙니다.

여담입니다만, 최근에는 프로젝트 하나 만드려면 공부해야 할께 너무 많네요..


다시 JSTL에 대해 돌아와서 이 언어를 JSP 페이지에서 사용하기 위해서는 pom.xml에 라이브러리를 추가해서 사용해야 합니다.

<dependencies>
  <!-- https://mvnrepository.com/artifact/org.apache.taglibs/taglibs-standard-impl -->
  <dependency>
    <groupId>org.apache.taglibs</groupId>
    <artifactId>taglibs-standard-impl</artifactId>
    <version>1.2.5</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/javax.servlet.jsp.jstl/jstl -->
  <dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
  </dependency>
</dependencies>

그리고 JSTL 라이브러리를 사용하기 위해서는 JSP 상단에 선언하고 사용하면 됩니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- JSTL 선언 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- HTML 태그 시작 -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <!-- 변수 선언 -->
    <c:set var="data" value="JSTL Hello world" />
    <!-- JSTL 언어로 변수 출력 -->
    ${data}
  </body>
</html>

JSTL 사용 방법은 라이브러리마다 접두어 사용법이 약간 다릅니다.

먼저 라이브러리는 5가지 종류가 있습니다. 일반 프로그램 언어를 처리하는 변수 선언, 출력 간단한 조건문, 반복문을 실행하는 코어가 있고, 숫자나 날짜, 시간등을 문자 형식의 포멧팅 기능, 국제화와 다국어 처리하는 포멧팅이 있습니다.

문자열을 다루는 함수가 있고 데이터 베이스와 XML 처리를 하는 기능도 있습니다.

이 다섯 가지 라이브러리는 사용 접두어가 다릅니다.

라이브러리 기능 URI 식별자 접두어
코어 일반 프로그램 언어에서 제공하는 제어처리를 하는 라이브러리 http://java.sun.com/jsp/jstl/core c

포멧팅

숫자,날짜,시간을 포맷팅 하는 기능과 국제화, 다국어 처리하는 라이브러리 http://java.sun.com/jsp/jstl/fmt fmt
함수 문자열을 처리하는 라이브러리 http://java.sun.com/jsp/jstl/functions fn
데이터베이스 데이터베이스의 관련 기능을 처리하는 라이브러리 http://java.sun.com/jsp/jstl/sql sql
XML처리 XML의 관련 기능을 처리하는 라이브러리 http://java.sun.com/jsp/jstl/xml x

코어 라이브러리

변수 선언과 변수 삭제 <c:set/>, <c:remove/>

기본적으로 view에서 사용하는 변수들은 controller 영역에서 선언하고 가져오는 처리입니다만, 사양에 따라 JSP 파일(view)에서 변수를 선언하고 또 중간에 변수를 재선언 또는 삭제가 필요할 수도 있습니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- JSTL 코어 선언 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- HTML 태그 시작 -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <!-- 변수 선언 -->
    <c:set var="data" value="hello world" scope="page" />
    <!-- 변수 출력 -->
    ${data}<br />
    <!-- 변수 삭제 -->
    <c:remove var="data" />
    <!-- 변수 출력 -->
    ${data}
  </body>
</html>

scope속성은 변수의 생명 주기 범위입니다.

page의 경우는 기본적으로 default 생명 주기로 브라우저에서 요청하고 응답할 때까지 영역입니다.

request는 page보다는 조금 긴 생명 주기로 요청하고 응답하고, 다시 페이지로 요청할 때까지 유지(서버에서 취득 가능)합니다. 즉, 서버에서 응답(response)되면 사라집니다.

session은 서버에서 session이 만료될 때까지 공유됩니다.

application은 사용자와 관계없이 서버 프로그램이 종료될 때까지 공유되는 영역입니다.

변수 출력 <c:out/>

JSTL에서는 변수 출력을 하는 것은 달러 표시와 중괄호로 데이터 값을 출력(${변수명})합니다.

그런데 이 변수 값안에 이스케이프 문자가 들어가면 변환되지 않고 그대로 출력해서 에러가 됩니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- JSTL 선언 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- HTML 태그 시작 -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <!-- 변수 선언 -->
    <c:set var="data" value="<Hello world>" />
    <!-- 변수 출력 -->
    ${data}
  </body>
</html>

위 예제를 보면 < >가 변환되지 않아 그대로 태그로 인식 해 버립니다.

그러나 보통은 이스케이프 변환을 하여 출력을 해야 합니다. 또 값이 null일 경우 기본 값을 처리하는 경우도 있습니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- JSTL 선언 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- HTML 태그 시작 -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <!-- 변수 선언 -->
    <c:set var="data" value="<Hello world>" />
    <!-- 변수 출력, 이스케이 변환, null인 경우 Not data를 출력한다. -->
    <c:out value="${data}" default="Not data" escapeXml="true"/>
  </body>
</html>

escapeXml 속성에 true를 넣으면 변수의 이스케이프하여 <와>가 출력이 됩니다. 생략하면 기본적으로 false로 이스케이프 변환되지 않습니다.

분기문 태그 <c:if/>

JSTL도 프로그래밍 언어의 종류이므로 기본적으로 분기문과 반복문이 존재합니다.

c:if는 분기분으로 해당 조건식에 참(true)의 경우에 태그의 안의 태그가 표시됩니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- JSTL 선언 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- HTML 태그 시작 -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <!-- 변수 선언 -->
    <c:set var="data" value="0" scope="page"/>
    <!-- 분기문 data가 0일 경우 -->
    <c:if test="${data eq 0}">
      <!-- if 분기문이 참이면 출력 -->
      <div>Hello world</div>
    </c:if>
  </body>
</html>

여기서 scope 속성은 <c:set/>에서 사용한 속성과 같은 의미입니다.

그리고 test 속성에서 사용한 eq 비교 표현식으로 empty, eq, ne가 있습니다.

empty는 변수가 비어있는지 아닌지 확인하는 것이고 eq는 같은 경우 참이고 ne는 다른 경우 참이 됩니다.

그리고 꼭 문자 연산자가 아닌 비교 연산자(< , >)와 논리 연산자(||, ==, !)등도 사용 가능합니다.

분기문 태그 <c:choose/>, <c:when/>, <c:otherwise/>

Java에서는 분기문 종류가 if와 if~else가 있습니다. JSTL은 if 분기 태그는 있습니다만 if~else 분기 태그는 없습니다.

대신에 switch와 비슷한 <c:choose/>, <c:when/>, <c:otherwise/> 분기문이 있습니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- JSTL 선언 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- HTML 태그 시작 -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <!-- 변수 선언 -->
    <c:set var="data" value="0" scope="page"/>
    <c:choose>
      <!-- 분기문 data가 0보다 작은 경우 -->
      <c:when test="${data < 0}">
           <div>Minus</div>
      </c:when>
      <!-- 분기문 data가 0인 경우 -->
      <c:when test="${data eq 0}">
        <div>Zero</div>
      </c:when>
      <!-- 그 외 -->
      <c:otherwise>
        <div>Plus</div>
      </c:otherwise>
    </c:choose>
  </body>
</html>

여기서 c:choose 태그는 자바의 switch와 같다면 when은 자바의 case와 otherwise는 자바의 default와 같은 의미입니다.

결과는 0이기 때문에 Zero의 태그가 화면이 표시되었습니다.

반복문 태그 <c:forEach/>

분기문이 있다면 반복문이 있습니다. 반복문은 여러 필수 속성이 있습니다.

속성 메소드 설명
current 현재 값
index 제로 기반(zero-based) 인덱스 값
count 1 기반(one-based) 인덱스 값
first 첫 번째 값 여부
last 마지막 값 여부
begin begin 속성의 값
end end 속성의 값
step step 속성의 값
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- JSTL 선언 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- HTML 태그 시작 -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <!-- 변수 선언 -->
    <c:set var="data" value="0" scope="page" />
    <!-- forEach 정수 범위내의 반복 -->
    <c:forEach var="i" begin="0" end="10" step="2" varStatus="x">
      <!-- index는 begin로 시작해서 end로 종료 인덱스 차이는 2가 됩니다. -->
      <!-- count는 반복이 몇번 발생했는지입니다.-->
      <!-- i와 x는 x는 반복문의 인덱스라면 x는 반복문 안에서 사용하는 변수 -->
      <div>${x.index}(${x.count}) = ${i*10}</div>
      <!-- 반복문의 처음이라면 -->
      <c:if test="${x.first}">
        <div>first = ${i*10}</div>
      </c:if>
      <!-- 반복문의 마지막이라면 -->
      <c:if test="${x.last}">
        <div>last = ${i*10}</div>
      </c:if>
    </c:forEach>
  </body>
</html>

반복문 태그 <c:forTokens/>

반복문 태그 <c:forEach/>와 비슷한 속성 종류를 사용합니다만 items에 조건 데이터를 놓고 delims로 구분(split)를 하고 iterater 패턴 형식으로 반복하는 차이가 있습니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- JSTL 선언 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- HTML 태그 시작 -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <!-- 변수 선언 -->
    <c:set var="data" value="0" scope="page" />
    <!-- items의 값을 |로 분할하여 반복한다. -->
    <c:forTokens var="color" items="red|orange|yellow|green|blue|indigo|purple" delims="|" varStatus="x" >
      ${x.count} = ${color}
    </c:forTokens>
  </body>
</html>

포멧팅 라이브러리

포멧팅은 정수나 실수의 자릿수 포함 문자로 변환, 혹은 문자를 정수나 실수로 표현하는 것, 그리고 날짜와 시간을 문자로 표현하는 태그입니다.

<fmt:formatNumber>

숫자를 문자로 변환하는 것과 관계된 포멧팅 태그입니다.

<fmt:formatNumber value="numericValue"
                 [type="{number|currency|percent}"]
                 [pattern="customPattern"]
                 [var="varName"]
                 [scope="{page|request|session|application}"]/>

type속성에서 number는 문자를 숫자로 표현하고 currency는 돈 형식으로 표현, percent는 퍼샌트 형식으로 표현합니다. pattern은 그 외의 패턴을 추가하는 것이고 var는 변수 설정입니다.

scope 속성은 <c:set/>에서 사용한 속성과 같은 의미입니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- 코어 라이브러리 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- 포멧팅 라이브러리 -->
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!-- HTML 태그 시작 -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <!-- 지역 설정 -->
    <fmt:setLocale value="ko_KR"/>
    <!-- 태그 안에 문자를 천단위로 콤마를 추가한다. -->
    <p>number  : <fmt:formatNumber type="number">1234567.89</fmt:formatNumber></p>
    <!-- 태그 안에 문자를 돈단위로 설정한다. 한국 돈은 소숫점이 존재하지 않으므로 반올림 처리한다. -->
    <p>currency : <fmt:formatNumber type="currency" currencySymbol="₩" >1234567.89</fmt:formatNumber> </p>
    <!-- 퍼센트 처리이므로 곱하기 100으로 표현한다. -->
    <p>percent : <fmt:formatNumber type="percent">0.159</fmt:formatNumber></p>
    <!-- 포멧 패턴을 설정한다. (소숫점 처리)-->
    <p>pattern=".000"    :<fmt:formatNumber value="1234567.1" pattern=".000" /></p>
    <!-- 포멧 패턴 설정한다. (소숫점 처리) -->
    <p>pattern="#,#00.0#":<fmt:formatNumber value="1234567.891" pattern="#,#00.0#"/></p>
  </body>
</html>

값은 태그 안의 값을 처리할 수도 있고 속성으로 value를 설정하여 화면에 표시할 수 있습니다.

<fmt:parseNumber/>

문자로 표현된 값을 숫자로 표현하는 태그입니다.

<fmt:parseNumber [type="{number|currency|percent}"]
                 [pattern="customPattern"]
                 [parseLocale="parseLocale"]
                 [integerOnly="{true|false}"]
                 [var="varName"]
                 [scope="{page|request|session|application}"]>

태그 속성은 <fmt:formatNumber>와 같습니다. integerOnly에서 true일 경우, 실수의 표현일 경우 소숫점이하는 버리고 정수만 표시한다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- 코어 라이브러리 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- 포멧팅 라이브러리 -->
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!-- HTML 태그 시작 -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <p>number  : <fmt:parseNumber value="1,234,567.89" type="number"/></p>
    <p>currency : <fmt:parseNumber value="12345abcdef.999" integerOnly="false" type="number" /></p> 
  </body>
</html>

<fmt:formatDate/>

변수에 java의 Date 클래스의 값으로 설정이 된 경우 포멧팅에 의해 화면에 표시할 수 있다.

<fmt:formatDate value="date"
               [type="{time|date|both}"]
               [dateStyle="{default|short|medium|long|full}"]
               [timeStyle="{default|short|medium|long|full}"]
               [pattern="customPattern"]
               [timeZone="timeZone"]
               [var="varName"]
               [scope="{page|request|session|application}"]/>

dateStyle와 timeStyle은 포멧팅 스타일의 길이를 설정하고 pattern은 yyyy/MM/dd와 같이 사용자가 패턴을 설정할 수 있습니다.

timeZone은 접속 지역을 설정할 수 있습니다. var는 변수 설정이고 scope 속성은 <c:set/>에서 사용한 속성과 같은 의미입니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!-- 코어 라이브러리 -->
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!-- 포멧팅 라이브러리 -->
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!-- HTML 태그 시작 -->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <c:set var="now" value="<%= new java.util.Date() %>" />
    <p> date full : <fmt:formatDate value="${now}" type="date" dateStyle="full" /></p>
    <p> date short : <fmt:formatDate value="${now}" type="date" dateStyle="short" /></p>
    <p> time : <fmt:formatDate value="${now}" type="time" /></p>
    <p> both full : <fmt:formatDate value="${now}" type="both" dateStyle="full" timeStyle="full" /></p>
    <p> pattern 1 : <fmt:formatDate value="${now}" pattern="yyyy-MM-dd aa hh:mm:ss" /></p>
    <p> pattern 2 : <fmt:formatDate value="${now}" pattern="yyyy-MM-dd  hh:mm:ss" /></p>
  </body>
</html>

참조 링크 - http://wiki.gurubee.net/pages/viewpage.action?pageId=26740270


다음 글에서 JSTL의 함수 라이브러리와 데이터 베이스 라이브러리를 정리하겠습니다.


여기까지 Web Spring framework의 view에서 사용하는 언어(JSTL) - 코어, 포멧팅에 대한 글이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.