Thymeleaf란?
- JSP를 대신하는 목적으로 작성된 라이브러리이고 템플릿 엔진이다.
- 템플릿 이기에 JSP 처럼 직접 데이터를 생성하지 않고 만들어진 결과에 데이터를 맞춰서 보여준다.
- 서버에서 동작하기는 하지만 HTML을 기반으로 화면을 구성하기 때문에 조금 더 HTML에 가까운 방식으로 작성된다.
사용 방법
HTML 파일 상단 네임스페이스에 <html xml:th="http://www.thymeleaf.org"> 태그를 추가한다.
th 태그를 사용해서 Model에 담긴 데이터를 사용할 때는 ‘해당 변수를 찾을 수 없다’ 라는 에러가 날 수 있다. (인텔리제이 버전에 따라 다름)
만일 에러가 발생하는 경우에는 인텔리제이의 설정을 변경해야하는데 다음과 같이 진행하면 된다. Setting → Thymeleaf 검색 → Unresolved references.. 체크 해제 → 이후 에디터(html 파일) 종료 후 실행
-> 변수에 대한 검사를 하지 않는 설정이다.
Thymeleaf 기초 문법
더보기
1. Model의 데이터 출력 방법
th 태그 방식, EL이랑 비슷하나 th 태그 포함
<h4 th:text=”${name}”/>
inLine 방식
[[${name}]]
2. 주석 처리
<!--/* ... */-->
→ 브라우저에 해당 부분이 아예 표시되지 않는다.
→ Thymeleaf가 파싱 처리할 때 삭제되어 처리됨, 잘못된 문법에 대한 체크를 건너뛸 수 있음
3. 임시변수 선언
<div th:with="num1 = ${10}, num2 = ${20}">
<h4 th:text="${num1 + num2}"/>
</div>
반복문과 제어문 처리
반복문
- 반복이 필요한 태그에: th:each
- 별도 태그: th:block
더보기
<!-- th:each 방식 -->
<ul>
<li th:each="str: ${list}" th:text="{str}"/>
</ul>
<!-- <th:block> -->
<ul>
<th:block th:each="str: ${list}">
<li> [[${str}]] </li>
</th:block>
</ul>
- 반복문의 status 변수
- → index/count/size/first/last/add/even
더보기
<ul>
<li th:each="str, status: ${list}">
[[${status.index}]] -- [[${str}]]
</li>
</ul>
<!-- index: 0, count: 1 -->
제어문
- th:if / th:unless / th:switch / 삼항연산자
더보기
<!-- th:if, th:unless -->
<ul>
<li th:each="str, status: ${list}">
<span th:if="${status.odd}"> ODD -- [[${str}]] </span>
<span th:unless="${status.odd"> EVEN -- [[${str}]] </span>
</li>
</ul>
<!-- 홀수번째만 -->
<ul>
<li th:each="str, status: ${list}">
<span th:text="${status.odd} ? 'ODD ---'+${str}"></span>
</li>
</ul>
<!-- 삼항 연산자 -->
<ul>
<li th:each="str, status: ${list}">
<span th:text="${status.odd} ? 'ODD ---'+${str} : 'EVEN ---'+${str}"></span>
</li>
</ul>
<!-- switch 문 -->
<ul>
<li th:each="str, status: ${list}">
<th:block th:switch="${status.index % 3}">
<span th:case="0">0</span>
<span th:case="1">1</span>
<span th:case="2">2</span>
</th:block>
</li>
</ul>
thymeleaf 링크 처리
- JSP와 달리 특정 프로젝트의 경로부터 시작하는 것을 고려하지 않아도 된다.
- ‘key=value’ 의 형태의 파라미터는 ‘()’를 이용한다.
- 쿼리 스트링에서 한글, 공백 문자 등에 대한 URL 인코딩 처리가 자동으로 이뤄진다.
- 배열과 같이 여러개 일 경우 자동으로 같은 이름의 파라미터를 처리함 (에디터는 오류로 출력하나 정상 동작)
더보기
<!-- @로 처리함 -->
<a th:href="@{/hello}">Go to /hello</a>
<!-- key=value 형태로 파라미터 처리 ( 쿼리 스트링 ) -->
<a th:href="@{/hello(name='AAA', age= 16)}">Go to /hello</a>
<!-- 링크의 쿼리 스트링 처리, URL 인코딩 자동 처리 -->
<a th:href="@{/hello(name='한글 처리', age= 16)}">Go to /hello</a>
<!-- 배열과 같이 여러 개 파라미터 처리 -->
<a th:href="@{/hello(types=${ {'AA', 'BB', 'CC'} }, age=16)}">Go to /hello</a>
인라인 요소를 자바스크립트 내에서 활용하는법
-> var conPath = /*[[ @{/} ]]*/;
: 실제는 @{/} 요걸로 호출된다. 저 앞뒤로 붙은 /[[ ]]/ 안에 있는 Thymeleaf 문법은 스크립트 영역 안에서도 호출이 유지되게 해준다. 그리고 스크립트나 정적 리소스 패스는 타임리프 태그 th 붙이고 @{} 안에 표현 하면 된다.
ex) script th:src="@{/js/jquery-3.5.1.min.js}"
그리고 물론 th 태그 사용은 페이지 상단에 " <html xmlns:th="http://www.thymeleaf.org"> "
이렇게 정의해줘야 된다.
Thymeleaf의 특별한 기능들
타임리프의 고유기능들은 JSTL과 유사하지만 JSP보다 더욱 발전되었다.
인라인 처리
인라인 기능은 동일한 데이터를 상황에 따라 다르게 출력해 주는 기능이다. 자바스크립트를 사용할 때 편리하다.
HTML 코드나 자바스크립트에 인라인 처리를 하면 객체들을 사용할 수 있다.
자바스크립트에서 인라인 기능을 사용하려면 <script th:inline=’javascript’> 키워드를 지정해야 한다. 해당 코드를 브라우저에서 확인하면 원래의 문법으로 변환되어 있다.
더보기
<!-- 컨트롤러 -->
class SampleDTO {
private String p1, p2, p3;
public String getP1() {
return p1;
}
public void setP1(String p1) {
this.p1 = p1;
}
public String getP2() {
return p2;
}
}
@GetMapping("/ex/ex2")
public void ex2(Model model) {
log.info("ex/ex2.........");
List<String> strList = IntStream.range(1, 10)
.mapToObj(i -> "Data" + i)
.collect(Collectors.toList());
model.addAttribute("list", strList);
Map<String, String> map = new HashMap<>();
map.put("A", "AAAA");
map.put("B", "BBBB");
model.addAttribute("map", map);
SampleDTO sampleDTO = new SampleDTO();
sampleDTO.p1 = "Value -- p1";
sampleDTO.p2 = "Value -- p2";
sampleDTO.p3 = "Value -- p3";
model.addAttribute("dto", sampleDTO);
}
<!-- view -->
<div th:text="${list}"></div>
<div th:text="${map}"></div>
<div th:text="${dto}"></div>
<script th:inline="javascript">
const list = [[${list}]]
const map = [[${map}]]
const dto = [[${dto}]]
console.log(list)
console.log(map)
console.log(dto)
</script>
레이아웃 구성
th:block 태그를 활용해 레이아웃을 작성하고 특정한 페이지에서는 필요한 부분만을 작성하는 방식으로 개발할 수 있다. 해당 작업을 위해선 별도의 라이브러리를 추가해야 한다.
더보기
// kotlin gradle 기준입니다.
implementation("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.1.0")
// groovy gradle
implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '3.1.0'
- <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout”> 추가
- layout:fragment 속성을 사용하면 다른 파일에서 해당 부분만 개발 가능
- 아래 코드를 사용해 새로운 화면 작성 시 해당 코드를 그대로 활용하여 원하는 영역만 작성 가능 (content/script)
- 코드
더보기
<!-- layout1.html -->
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Layout page</title>
</head>
<body>
<div>
<h3>Sample Layout Header</h3>
</div>
<div layout:fragment="content">
<p>Page content goes here</p>
</div>
<div>
<h3>Sample Layout Footer</h3>
</div>
<th:block layout:fragment="script">
</th:block>
</body>
</html>
위의 코드로 구현된 fragment 단에 다음과 같이 추가하여 사용할 수 있음
더보기
<!--
~{...}는 Thymeleaf의 표현식 문법으로, 리소스 경로를 해석하는데 사용됩니다.
여기서는 "layout/layout1.html"이라는 경로의 레이아웃 템플릿을 사용하겠다는 의미입니다.
-->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layout/layout1.html}">
<div layout:fragment="content">
<h1>ex3.html</h1>
</div>
<script layout:fragment="script" th:inline="javascript">
const arr = [[${arr}]]
</script>
</html>
출력 결과
이외에도 여러 빌트인 객체와 기능들이 존재함