Spring Boot/thymeleaf

타임리프 기본 표현식

테토 2023. 10. 27. 16:35
반응형

 

타임리프란?

  1. 타임리프는 SSR(Server Side Render)을 하는 템플릿 엔진으로 백엔드 서버에서 HTML을 동적으로 렌더링 한다.
  2. 순수 HTML을 최대한 유지하기 때문에 html을 서버를 거치지 않고 직접 열어도 내용을 확인할 수 있다(당연히 동적으로 렌더링되지 않음)  => 이처럼 순수 html을 그대로 유지하면서 뷰 템플릿도 사용할 수 있는 특징을 내츄럴 템플릿이라고 함
  3. 스프링의 기능을 편리하게 사용할 수 있다. 
  4. 보통 간단한 화면을 구현할 때 사용된다
  5. html 문서에 선언을 추가하여 사용할 수 있다
<html xmlns:"http://www.thymeleaf.org">

 

타임리프의 기본 표현식

1. 텍스트 출력

타임리프는 기본적으로 html 태그에 th: 로 시작되는 기능을 속성으로 추가하여 사용할 수 있다 

텍스트 출력은 th:text 를 사용한다

 

<span th:text="${data}></span>

 

다음과 같은 경우 서버에서 넘어온 data의 값이 span태그 사이에 출력된다 

 

태그 밖에서 텍스트를 출력하고 싶은 경우 [[...]]를 사용한다

 

[[${data}]]

 

다음과 같은 경우에도 서버에서 넘어온 data값이 출력된다

 

그리고 타임리프는 서버에서 넘어오는 값을 자동으로 escape처리 해준다 

예를들어 <b> 태그를 사용했을 경우 &lt;b&gt; 로 전달된다 

이를 적용시키고 싶지 않은 경우 th:utext 또는 [(....)]를 사용한다

=> 데이터값을 받아와도 태그로 동작하기 때문에 의도하지 않은 상황 발생 가능, 안쓰는게 좋다

 

2. SpringEL 

SpringEL은 Spring express language로 타임리프 내에서 변수를 사용가능하게 해준다

위의 ${data} 처럼 사용한다

 

 User userA = new User("userA", 10);
 User userB = new User("userB", 20);
 
 List<User> list = new ArrayList<>();
 list.add(userA);
 list.add(userB);
 
 Map<String, User> map = new HashMap<>();
 map.put("userA", userA);
 map.put("userB", userB);
 
 
 model.addAttribute("user", userA);
 model.addAttribute("users", list);
 model.addAttribute("userMap", map);

 

다음과 같이 서버에서 model에 값을 넣어서 넘겨준다 (userA의 경우 username과 age를 가진 object임)

 

Object  

${user.username}
${user['username']}
${user.getUsername()}

 

List

${users[0].username}
${users[0]['username']}
${users[0].getUsername()}

 

Map

${userMap['userA'].username}
${userMap['userA']['username']}
${userMap['userA'].getUsername()}

 

지역변수

th:with로 변수 선언하면 선언한 태그 내에서만 사용되는 지역변수가 된다

<div th:with="hello=${data}">
	<p>안녕하세요 <span th:text="${data.username}"></span>입니다</p>
</div>

 

3. 기본 객체

 

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

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

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

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

${#locale}

 

파라미터 정보를 받아오려면 request.getParameter()로 접근해야하기 때문에 더 간단하게 접근할 수 있도록 편의 객체를 제공한다. 

${param.paramData}
${session.sessionData}
${@helloBean.hello('Spring!')}

편의객체를 통해 파라미터 정보, 세션 정보를 쉽게 받아올 수 있고 @를 이용하여 스프링빈에 직접 접근도 가능하다

 

4. 유틸리티 객체

타임리프 공식문서 참고해서 사용하기

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#expression-utility-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

https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#appendix-b-expression-utility-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에서 나온 LocalDate 관련 유틸리티 객체 사용

 

<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>

 

 

5. URL 링크

타임리프에서 url생성 시 @{...} 사용

 

<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>

 

param1 = data1, param2 = data2 일때

 

@{/hello}

=> /hello

 

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

=> /hello?param1=data1&param2=data2 

경로 뒤 () 부분이 파라미터로 처리됨

 

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

=> /hello/data1/data2

경로에 변수가 있으면 () 부분이 경로 변수로 처리됨

 

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

=> /hello/data1?param2=data2

경로에 있는 변수는 경로 변수로 처리되고 나머지는 쿼리파라미터로 처리됨

 

 

6. 리터럴

소스 코드상에 고정된 값 

상수과 헷갈렸었는데 상수와 다름 

리터럴은 진짜 말 그대로 값 자체이고 상수는 리터럴을 이용해서 초기화시킨 변하지 않는 값임

 

리터럴의 경우 무조건 ' ' 로 감싸주어야 하지만 공백이 없는 경우 그냥 써도 리터럴로 인식됨

공백이 포함된 경우 ' '로 감싸주어야 함 

변수를 포함할 경우 'hello' + ${data} 와 같이 사용하거나, 리터럴 대체를 사용할 수 있음

리터럴 대체의 경우 |...|의 형식으로  

|hello ${data}| 처럼 사용하면 하나의 리터럴로 인식됨

 

 

7. 연산

th:text 에 포함시 계산된 후 출력됨

 

<li>1 > 10 = <span th:text="1 > 10"></span></li>
<li>1 > 10 = <span th:text="1 gt 10"></span></li>
<li>1 > 10 = <span th:text="1 &gt; 10"></span></li>

셋 다 동일한 비교연산

비교 연산 시 불리언으로 출력. html 엔티티를 사용할 수도 있음

( > (gt), < (lt), >= (ge), <= (le), ! (not), == (eq), != (neq, ne)) <- SpEL을 지원하기 때문에 &;를 붙이지 않고도 사용가능

 

<li>(10 % 2 == 0)? '짝수':'홀수' = <span th:text="(10 % 2 == 0)? '짝수':'홀수'"></span></li>

조건식 

자바의 조건식과 유사함 10%2 == 0이 true면 짝수, false면 홀수 출력

 

<li>${data}?: '데이터가 없습니다.' = <span th:text="${data}?: '데이터가 없습니다.'"></span></li>
<li>${nullData}?: '데이터가 없습니다.' = <span th:text="${nullData}?: '데이터가 없습니다.'"></span></li>

Elvis 연산자 ?: 

? 앞의 값이 null이 아닐 시 값만 출력함

? 앞이 null이면 Elvis연산자의 뒷 부분을 출력함

 

<li>${data}?: _ = <span th:text="${data}?: _">데이터가 없습니다.</span></li>
<li>${nullData}?: _ = <span th:text="${nullData}?: _">데이터가 없습니다.</span></li>

No-operation ?:_

? 앞의 값이 null이 아닐시 값만 출력함

null이면 th:text무시하고 원래대로 동작함

 

 

8. 속성

기본적으로는 속성앞에 th: 를 붙여서 지정할 경우 서버에서 렌더링이 될 때 기존속성을 대체하거나 없는 경우 생성한다

 

다음 방법은 기존 속성을 대체하지 않고 기존 값에 값을 추가해 준다

th:attrappend = "class=' large'" 

=> class 속성 뒤에 ' large'를 붙인다
th:attrprepend = "class='large '"

=> class 속성 뒤에 'large '를 붙인다
th:classappend = "large"

=> class 속성 뒤에 붙인다. 띄어쓰기 안해줘도 알아서 띄어서 붙여준다

 

checkbox type의 경우 checked 속성이 포함 되어있기만 하면 체크되기에 불편하다

=> th:checked 를 이용해 true면 값포함 , false면 checked속성을 넣지 않음으로 체크 설정이 가능하다

 

 

9. 반복

자바의 for(String item : list){ } 와 비슷하게 th:each를 사용할 수 있다

 

<tr th:each="user : ${users}">
    <td th:text="${user.username}">username</td>
    <td th:text="${user.age}">0</td>
</tr>

${users} 순서대로 처음부터 끝까지 반복

userStat 이용시 다양한 정보 얻을 수 있음

userStat.index: 0부터 시작

userStat.count: 1부터 시작

userStat.size: 전체 사이즈

userStat.even, userStat.odd: 홀수 짝수 여부

userStat.first, userStat.last: 처음, 마지막 여부

userStat.current: 현재 객체

 

 

10. 조건부 평가

th:if , th:unless를 사용한다

조건이 맞지 않으면 조건문이 들어간 태그를 렌더링하지 않는다 

th:case 의 경우 다음과 같이 사용한다

<span th:case="10">10살</span>
<span th:case="20">20살</span>
<span th:case="*">기타</span>

 

 

11. 주석

표준 html 주석

<!--
<span th:text="${data}">html data</span>
-->

타임리프가 렌더링하지 않는다

서버없이 열었을 때도 주석으로 동작한다

 

 

타임리프 파서 주석

<!--/* [[${data}]] */-->

<!--/*-->
<span th:text="${data}">html data</span>
<!--*/-->

타임리프의 주석이다 렌더링할때 주석부분을 없애서 전달한다

두번째 주석의 경우 서버 없이 열었을 때는 보인다

 

 

타임리프 프로토타입 주석

<!--/*/
<span th:text="${data}">html data</span>
/*/-->

html주석으로 처리되기 때문에 파일로 열었을때는 보이지 않지만 타임리프 렌더링을 거치면 보이게 된다

 

 

12. 블록

<th:block> </th:block>으로 사용한다 

th: 태그를 html태그에 넣어서 사용하기 애매한 경우에 사용한다

 

 

참고한 강의

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-2/

반응형