본문 바로가기

spring

타임리프 - 기본 기능 (2)


기본 객체들

  • ${#request} - 스프링 부트 3.0부터 제공하지 않는다.
  • ${#response} - 스프링 부트 3.0부터 제공하지 않는다.
  • ${#session} - 스프링 부트 3.0부터 제공하지 않는다.
  • ${#servletContext} - 스프링 부트 3.0부터 제공하지 않는다.
  • ${#locale}

스프링 부트 3.0 부터는 ${#request} , ${#response} , ${#session} , ${#servletContext} 를 지원하지 않는다.

스프링 부트 3.0이라면 직접 model 에 해당 객체를 추가해서 사용해야 한다.

@GetMapping("/basic-objects")
public String basicObjects(HttpSession session) {
 session.setAttribute("sessionData", "Hello Session");
 return "basic/basic-objects";
}
@Component("helloBean")
static class HelloBean {
 public String hello(String data) {
 return "Hello " + data;
 }
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>
<h1>식 기본 객체 (Expression Basic Objects)</h1>
<ul>
 <li>request = <span th:text="${#request}"></span></li>
 <li>response = <span th:text="${#response}"></span></li>
 <li>session = <span th:text="${#session}"></span></li>
 <li>servletContext = <span th:text="${#servletContext}"></span></li>
 <li>locale = <span th:text="${#locale}"></span></li>
</ul>
<h1>편의 객체</h1>
<ul>
 <li>Request Parameter = <span th:text="${param.paramData}"></span></li>
 <li>session = <span th:text="${session.sessionData}"></span></li>
 <li>spring bean = <span th:text="${@helloBean.hello('Spring!')}"></span></li>
</ul>
</body>
</html>

위의 컨트롤러에는 session의 값을 담아가는 매핑주소와 직접 자바빈을 등록한 Component가 보인다.

아래에 html 코드에서 출력하는 모습을 확인해 보자.

스프링3.0이상부터는 아래처럼 작성하면 된다.

@GetMapping("/basic-objects")
public String basicObjects(Model model, HttpServletRequest request,
HttpServletResponse response, HttpSession session) {
 session.setAttribute("sessionData", "Hello Session");
 model.addAttribute("request", request);
 model.addAttribute("response", response);
 model.addAttribute("servletContext", request.getServletContext());
 return "basic/basic-objects";
}
@Component("helloBean")
static class HelloBean {
 public String hello(String data) {
 return "Hello " + data;
 }
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>
<h1>식 기본 객체 (Expression Basic Objects)</h1>
<ul>
 <li>request = <span th:text="${request}"></span></li>
 <li>response = <span th:text="${response}"></span></li>
 <li>session = <span th:text="${session}"></span></li>
 <li>servletContext = <span th:text="${servletContext}"></span></li>
 <li>locale = <span th:text="${#locale}"></span></li>
</ul>
<h1>편의 객체</h1>
<ul>
 <li>Request Parameter = <span th:text="${param.paramData}"></span></li>
 <li>session = <span th:text="${session.sessionData}"></span></li>
 <li>spring bean = <span th:text="${@helloBean.hello('Spring!')}"></span></li>
</ul>
</body>
</html>

HTTP 요청 파라미터 접근: param

예) ${param.paramData}

HTTP 세션 접근: session

예) ${session.sessionData}

스프링 빈 접근: @

예) ${@helloBean.hello('Spring!')}


유틸리티 객체와 날짜

타임리프는 문자, 숫자, 날짜, URI등을 편리하게 다루는 다양한 유틸리티 객체들을 제공한다.

타임리프 유틸리티 객체들

  • #message : 메시지, 국제화 처리
  • #uris : URI 이스케이프 지원
  • #dates : java.util.Date 서식 지원
  • #calendars : java.util.Calendar 서식 지원
  • #temporals : 자바8 날짜 서식 지원
  • #numbers : 숫자 서식 지원
  • #strings : 문자 관련 편의 기능
  • #objects : 객체 관련 기능 제공
  • #bools : boolean 관련 기능 제공
  • #arrays : 배열 관련 기능 제공
  • #lists , #sets , #maps : 컬렉션 관련 기능 제공
  • #ids : 아이디 처리 관련 기능 제공, 뒤에서 설명

타임리프 유틸리티 객체

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#expression-utilityobjects

 

Tutorial: Using Thymeleaf

1 Introducing Thymeleaf 1.1 What is Thymeleaf? Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text. The main goal of Thymeleaf is to provide a

www.thymeleaf.org

유틸리티 객체 예시

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#appendix-b-expressionutility-objects

 

Tutorial: Using Thymeleaf

1 Introducing Thymeleaf 1.1 What is Thymeleaf? Thymeleaf is a modern server-side Java template engine for both web and standalone environments, capable of processing HTML, XML, JavaScript, CSS and even plain text. The main goal of Thymeleaf is to provide a

www.thymeleaf.org

자바8 날짜

타임리프에서 자바8 날짜인 LocalDate , LocalDateTime , Instant 를 사용하려면 추가 라이브러리가 필요하다. 스프링 부트 타임리프를 사용하면 해당 라이브러리가 자동으로 추가되고 통합된다.

자바8 날짜용 유틸리티 객체 = #temporals

<span th:text="${#temporals.format(localDateTime, 'yyyy-MM-dd HH:mm:ss')}"></span>

@GetMapping("/date")
public String date(Model model) {
 model.addAttribute("localDateTime", LocalDateTime.now());
 return "basic/date";
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>
<h1>LocalDateTime</h1>
<ul>
 <li>default = <span th:text="${localDateTime}"></span></li>
 <li>yyyy-MM-dd HH:mm:ss = <span th:text="${#temporals.format(localDateTime,'yyyy-MM-dd HH:mm:ss')}"></span></li>
</ul>
<h1>LocalDateTime - Utils</h1>
<ul>
 <li>${#temporals.day(localDateTime)} = <span th:text="${#temporals.day(localDateTime)}"></span></li>
 <li>${#temporals.month(localDateTime)} = <span th:text="${#temporals.month(localDateTime)}"></span></li>
 <li>${#temporals.monthName(localDateTime)} = <span th:text="${#temporals.monthName(localDateTime)}"></span></li>
 <li>${#temporals.monthNameShort(localDateTime)} = <span th:text="${#temporals.monthNameShort(localDateTime)}"></span></li>
 <li>${#temporals.year(localDateTime)} = <span th:text="${#temporals.year(localDateTime)}"></span></li>
 <li>${#temporals.dayOfWeek(localDateTime)} = <span th:text="${#temporals.dayOfWeek(localDateTime)}"></span></li>
 <li>${#temporals.dayOfWeekName(localDateTime)} = <span th:text="${#temporals.dayOfWeekName(localDateTime)}"></span></li>
 <li>${#temporals.dayOfWeekNameShort(localDateTime)} = <span th:text="${#temporals.dayOfWeekNameShort(localDateTime)}"></span></li>
 <li>${#temporals.hour(localDateTime)} = <span th:text="${#temporals.hour(localDateTime)}"></span></li>
 <li>${#temporals.minute(localDateTime)} = <span th:text="${#temporals.minute(localDateTime)}"></span></li>
 <li>${#temporals.second(localDateTime)} = <span th:text="${#temporals.second(localDateTime)}"></span></li>
 <li>${#temporals.nanosecond(localDateTime)} = <span th:text="${#temporals.nanosecond(localDateTime)}"></span></li>
</ul>
</body>
</html>

URL 링크

타임리프에서 URL을 생성할 때는 @{...} 문법을 사용하면 된다.

@GetMapping("/link")
public String link(Model model) {
 model.addAttribute("param1", "data1");
 model.addAttribute("param2", "data2");
 return "basic/link";
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>
<h1>URL 링크</h1>
<ul>
 <li><a th:href="@{/hello}">basic url</a></li>
 <li><a th:href="@{/hello(param1=${param1}, param2=${param2})}">hello query param</a></li>
 <li><a th:href="@{/hello/{param1}/{param2}(param1=${param1}, param2=${param2})}">path variable</a></li>
 <li><a th:href="@{/hello/{param1}(param1=${param1}, param2=${param2})}">path variable + query parameter</a></li>
</ul>
</body>
</html>

단순한 URL

@{/hello} /hello

쿼리 파라미터

@{/hello(param1=${param1}, param2=${param2})}

→ /hello?param1=data1¶m2=data2

→ () 에 있는 부분은 쿼리 파라미터로 처리된다.

경로 변수

@{/hello/{param1}/{param2}(param1=${param1}, param2=${param2})}

 /hello/data1/data2

→ URL 경로상에 변수가 있으면 () 부분은 경로 변수로 처리된다.

경로 변수 + 쿼리 파라미터

@{/hello/{param1}(param1=${param1}, param2=${param2})}

 /hello/data1?param2=data2

→ 경로 변수와 쿼리 파라미터를 함께 사용할 수 있다.


리터럴 (Literals)

타임리프는 다음과 같은 리터럴이 있다.

  1. 문자: 'hello'
  2. 숫자: 10
  3. 불린: true , false
  4. null: null
  5. 타임리프에서 문자 리터럴은 항상 ' (작은 따옴표)로 감싸야 한다. 
    예) <span th:text="'hello'">

그런데 문자를 항상 ' 로 감싸는 것은 너무 귀찮은 일이다. 

공백 없이 쭉 이어진다면 하나의 의미있는 토큰으로 인지해서 다음과 같이 작은 따옴표를 생략할 수 있다.
룰: A-Z , a-z , 0-9 , [] , . , - , _
<span th:text="hello">

 

오류

<span th:text="hello world!"></span> 문자 리터럴은 원칙상 ' 로 감싸야 한다. 중간에 공백이 있어서 하나의 의미있는 토큰으로도 인식되지 않는다.

<span th:text="'hello world!'"></span>
이렇게 ' 로 감싸면 정상 동작한다.

@GetMapping("/literal")
public String literal(Model model) {
 model.addAttribute("data", "Spring!");
 return "basic/literal";
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>
<h1>리터럴</h1>
<ul>
 <!--주의! 다음 주석을 풀면 예외가 발생함-->
<!-- <li>"hello world!" = <span th:text="hello world!"></span></li>-->
 <li>'hello' + ' world!' = <span th:text="'hello' + ' world!'"></span></li>
 <li>'hello world!' = <span th:text="'hello world!'"></span></li>
 <li>'hello ' + ${data} = <span th:text="'hello ' + ${data}"></span></li>
 <li>리터럴 대체 |hello ${data}| = <span th:text="|hello ${data}|"></span></li>
</ul>
</body>
</html>

리터럴 대체(Literal substitutions)

<span th:text="|hello ${data}|">
마지막의 리터럴 대체 문법을 사용하면 마치 템플릿을 사용하는 것 처럼 편리하다.


연산

타임리프 연산은 자바와 크게 다르지 않다. HTML안에서 사용하기 때문에 HTML 엔티티를 사용하는 부분만 주의하자.

@GetMapping("/operation")
public String operation(Model model) {
 model.addAttribute("nullData", null);
 model.addAttribute("data", "Spring!");
 return "basic/operation";
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>
<ul>
 <li>산술 연산
 <ul>
 <li>10 + 2 = <span th:text="10 + 2"></span></li>
 <li>10 % 2 == 0 = <span th:text="10 % 2 == 0"></span></li>
 </ul>
 </li>
 <li>비교 연산
 <ul>
 <li>1 > 10 = <span th:text="1 &gt; 10"></span></li>
 <li>1 gt 10 = <span th:text="1 gt 10"></span></li>
 <li>1 >= 10 = <span th:text="1 >= 10"></span></li>
 <li>1 ge 10 = <span th:text="1 ge 10"></span></li>
 <li>1 == 10 = <span th:text="1 == 10"></span></li>
 <li>1 != 10 = <span th:text="1 != 10"></span></li>
 </ul>
 </li>
 <li>조건식
 <ul>
 <li>(10 % 2 == 0)? '짝수':'홀수' = <span th:text="(10 % 2 == 0)?'짝수':'홀수'"></span></li>
 </ul>
 </li>
 <li>Elvis 연산자
 <ul>
 <li>${data}?: '데이터가 없습니다.' = <span th:text="${data}?: '데이터가없습니다.'"></span></li>
 <li>${nullData}?: '데이터가 없습니다.' = <span th:text="${nullData}?:'데이터가 없습니다.'"></span></li>
 </ul>
 </li>
 <li>No-Operation
 <ul>
 <li>${data}?: _ = <span th:text="${data}?: _">데이터가 없습니다.</span></li>
 <li>${nullData}?: _ = <span th:text="${nullData}?: _">데이터가없습니다.</span></li>
 </ul>
 </li>
</ul>
</body>
</html>

비교연산 : HTML 엔티티를 사용해야 하는 부분을 주의하자,

> (gt), < (lt), >= (ge), <= (le), ! (not), == (eq), != (neq, ne)

조건식 : 자바의 조건식과 유사하다.

Elvis 연산자 : 조건식의 편의 버전

No-Operation : _ 인 경우 마치 타임리프가 실행되지 않는 것 처럼 동작한다. 이것을 잘 사용하면 HTML 의 내용 그대로 활용할 수 있다. 마지막 예를 보면 데이터가 없습니다. 부분이 그대로 출력된다.

 

'spring' 카테고리의 다른 글

타임리프 - 기본 기능 (4)  (0) 2023.04.11
타임리프 - 기본 기능 (3)  (0) 2023.04.10
타임리프 - 기본 기능 (1)  (0) 2023.04.10
PRG Post/Redirect/Get  (0) 2023.04.05
간단한 사이트 만들기  (0) 2023.04.05