본문 바로가기
실습/리눅스 서버 + 스프링 부트

[스프링부트] Thymeleaf

by 이민우 2021. 9. 26.
728x90
반응형

Thymeleaf

타임리프란, 자바 기반의 템플릿 엔진으로 MVC 패턴에 적합하게 설계된 템플릿 엔진이다.

 

타임리프는 View Template이라고도 불리는데, 이는 컨트롤러가 전달하는 데이터를 이용하여 동적으로 화면을 구성할 수 있게 해준다.

 

 

 

JSP vs Thymeleaf

 

jsp를 사용한 웹 어플리케이션 제작시, 자바 프로젝트 파일은 필연적으로 war 파일로 만들어진다. 그리고 war 파일은 jar 파일에 비해, jsp의 해석과 관련된 모든 패키지들이 포함되며 무거운 구조가 되었다.

https://pediaa.com/what-is-the-difference-between-jar-and-war-files/

타임리프는 HTML을 기반으로 하기에 굳이 war로 말 필요 없이 jar 파일로 말아서 사용할 수 있고,

덕분에 war이라는 무거운 구조에서 벗어날 수 있게 되었다.

 

 

활용법

 

스프링 부트을 기준으로 사용법은 web.xml에 다음 디펜던시를 추가하는 것이다.

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

 

그리고 application.properties에서 세부 설정을 할 수 있다.

#cache가 false일 경우 html 수정 시 재가동할 필요 없이 웹에서 확인 가능. (개발용)
spring.thymeleaf.cache=false

#타임리프 폴더의 prefix와 suffix
spring.thymeleaf.prefix=classpath:templates/
spring.thymeleaf.suffix=.html

#템플릿을 렌더링하기 전 템플릿의 존재 여부 확인
spring.thymeleaf.check-template=true

#템플릿 위치의 존재 여부 확인
spring.thymeleaf.check-template-location=true

#웹 프레임워크에 대한 타임리프 보기 확인 활성화 여부
spring.thymeleaf.enabled=true

#springEL 컴파일러 활성화
spring.thymeleaf.enable-spring-el-compiler=false

#템플릿 파일 인코딩 설정
spring.thymeleaf.encoding=UTF-8

#확인에서 제외해야 하는 쉼표로 구분된 보기 이름(패턴 허용) 목록
spring.thymeleaf.excluded-view-names=

#템플릿에 적용할 템플릿 모드
spring.thymeleaf.mode=HTML

#최대 청크 크기가 설정되었을 때 CHUNKED 모드에서 실행되는 유일한 보기 이름(패턴 허용)의 쉼표로 구분된 목록
spring.thymeleaf.reactive.chunked-mode-view-names=

#최대 청크 크기가 설정되어 있더라도 FULL 모드에서 실행되어야 하는 쉼표로 구분된 보기 이름(패턴 허용) 목록
spring.thymeleaf.reactive.full-mode-view-names=

#응답에 쓰는 데 사용되는 데이터 버퍼의 최대 크기
spring.thymeleaf.reactive.max-chunk-size=0B

#보기 기술이 지원하는 미디어 유형
spring.thymeleaf.reactive.media-types=

#체크박스의 마커 역할을 하는 숨겨진 양식 입력이 체크박스 요소 자체보다 먼저 렌더링되어야 하는지 여부
spring.thymeleaf.render-hidden-markers-before-checkboxes=false

#HTTP 응답에 기록된 Content-Type 값
spring.thymeleaf.servlet.content-type=text/html

#Thymeleaf가 가능한 한 빨리 부분 출력 쓰기를 시작해야 하는지 아니면 템플릿 처리가 완료될 때까지 버퍼링해야 하는지 여부
spring.thymeleaf.servlet.produce-partial-output-while-processing=true

#체인에서 템플릿 해석기의 순서
spring.thymeleaf.template-resolver-order=

#확인할 수 있는 보기 이름(패턴 허용)의 쉼표로 구분된 목록
spring.thymeleaf.view-names=

출처: https://frontbackend.com/thymeleaf/thymeleaf-default-spring-boot-application-properties

 

 

 

활용법 : 기본 변수

 

기본적으로 ModelAndView를 사용하면 addObject 함수를 사용하여 (키, 값) 으로 넣어서 데이터를 전송할 수 있다.

@Controller
public class test {
	@RequestMapping(value = {"/test"}, method= RequestMethod.GET})
	public ModelAndView test() {
		ModelAndView mav = new ModelAndView("test"); // prefix, suffix와 결합되어 classpath:template/test.html 이 된다.
		
		String strSample = "test";
		int intSample = 0;
		
		mav.addObject("strSample", strSample); //키-값 쌍으로 삽입
		mav.addObject("intSample", intSample);
		
		return mav;
	}
}

 

그리고 HTML에서는 th:<type> = "${키값}" 안에서 사용이 가능하다.

<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>         
	<table>
	    <tr> <th colspan = "2"> PrimitiveTypeSamples </th></tr>
	    <tr> <td> <span th:text = "${intSample}">intSample</span> </td> </tr>
	    <tr> <td> <span th:text = "${strSample}">strSample</span> </td> </tr>
	</table>
</body>
</html>

 

 

 

활용법 : 자료구조

 

기본 변수 외에도 List, Map과 같은 자료구조들도 전송 및 활용이 가능하다.

//맵
Map<String, String> mapSample = new HashMap<String, String>();
mapSample.put("key1", "val1");
mapSample.put("key2", "val2");
		
//리스트
List<String> listSample = new ArrayList<String>();
listSample.add("list1");
listSample.add("list2");
		
mav.addObject("mapSample", mapSample);
mav.addObject("listSample", listSample);

 

마찬가지로 HTML에서는 th:<type> = "${키값}" 으로 사용이 가능하다.

여기서 리스트와 맵에서 각 객체를 뽑아올 때는 아래와 같이 for-each 구문과 비슷하게 사용을 한다.

또한 자료구조에는 .empty 와 th:if 문을 활용해 각 자료구조가 비었는지를 사전에 확인할 수 있다.

여기서 else로는 unless를 사용하는데, else와 완전히 같지는 않고, 조건문 안의 내용이 false 일 경우 실행되게 된다.

<tr> <th colspan = "2"> MapSamples </th> </tr>
<tr th:if="${mapSample.empty}">
	<th colspan = "2"> empty list </th>
</tr>
<tr th:unless="${mapSample.empty}" th:each="sample : ${mapSample}">
	<td> <span th:text = "${sample.key}"> key </span> </td>
	<td> <span th:text = "${sample.value}"> value </span> </td>
</tr>
         
<tr> <th colspan = "2"> ListSamples </th> <tr>
<tr th:if="${listSample.empty}">
	<th colspan = "2"> empty list </th>
</tr>
<tr th:unless="${listSample.empty}" th:each="sample : ${listSample}">
	<td> <span th:text = "${sample}" colspan = "2">sample</span></td>
</tr>

굳이 for-each를 사용하지 않고 Map 내의 Value를 가져오고 싶다면 ${mapSample['key1']} 과 같이 가져올 수 있다.

 

 

활용법 : Object

 

id, name 라는 두 개의 String 멤버 변수를 가진 TestObject 클래스를 만들어서 활용해보자.

메인에 들어갈 추가 코드는 다음과 같다.

//객체
TestObject objectSample = new TestObject("id", "name");

//객체 리스트
List<TestObject> objectListSample = new ArrayList<>();
objectListSample.add(new TestObject("id1", "name1"));
objectListSample.add(new TestObject("id2", "name2"));

mav.addObject("objectSample", objectSample);
mav.addObject("objectListSample", objectListSample);

 

그리고 HTML에는 다음과 같이 들어가게 된다. 사용법은 앞에서 설명한 내용과 같다.

단 여기서 주의할 점은 getId() 와 같은 함수가 아닌 id 라는 변수를 직접적으로 가져오는 듯한 문법을 사용한다. 만약 멤버 변수가 public이라면 가져올 수 있으나, 당연하게도 대부분의 변수들은 private으로 선언이 되어있을 것이다.

하지만 걱정할 것이 없는게, public으로 선언된 getter 함수가 존재한다면, 아래와 같은 방식으로도 타임리프 내에서 객체의 멤버 변수에 접근이 얼마든지 가능해진다.

 

즉, 변수를 public으로 할 게 아니라면 타임리프 내에서 변수 접근을 위해 getter 함수가 필요하다.

<tr> <th colspan = "2"> ObjectSamples </th> </tr>
<tr> 
   <td> <span th:text = "${objectSample.id}"> id </span> </td>
   <td> <span th:text = "${objectSample.name}"> name </span> </td>
</tr>

<tr> <th colspan = "2"> ObjectListSamples </th> </tr>
<tr th:if="${objectListSample.empty}">
   <th colspan = "2"> empty list </th>
</tr> 
<tr th:unless="${objectListSample.empty}" th:each="sample : ${objectListSample}">
   <td> <span th:text = "${sample.id}"> id </span> </td>
   <td> <span th:text = "${sample.name}"> name </span> </td>
</tr>

 

 

 

활옹법 : 여러 변수 사용

 

Hello 와 World 를 서로 다른 변수에 담아서 보내주고 한 문장 속에서 보여주기 위해서는 어떻게 해야할까?

혹은 한 변수에 추가적으로 어떤 문구를 추가해서 사용하고 싶으면 어떻게 해야할까?

String str1 = "Hello";
String str2 = "World";

mav.addObject("str1", str1);
mav.addObject("str2", str2);

 

생각만으로는 그냥 th:text="${변수1} ${변수2}" 이렇게 보내주면 될 것 같지만, 아쉽게도 org.thymeleaf.exceptions.TemplateProcessingException: Could not parse as expression

이 발생하게 된다.

또한 th:text="${변수} abcd" 와 같이 변수 + 문자열의 조합도 같은 오류를 발생시킨다.

이에 대한 해결법은 간단하다. | | 안에 감싸서 사용하면 여러 개의 변수들을 사용할 수 있다.

또한 | | 안에는 변수 뿐 아니라 일반 문자와 띄어쓰기 등을 함께 사용할 수 있다.

<span th:text="|${str1}${str2}|"></span>
<span th:text="|${str1} everyone. Welcome to ${str2}|"></span>

 

 

 

활용법 : 자바 스크립트

 

자바 스크립트 내에서 HTML과 같이 "${변수명}"은 사용할 수 없다.

자바 스크립트에서 타임리프 변수를 사용하는 법은 [[ ]] 안에 넣어서 사용하는 것이다.

물론 th:text="${str1} ${str2}" 가 안되는 것처럼, 같은 [[ ]] 안에 넣을 수는 없고,

각 변수를 [[ ]] 안에 넣어서 사용하면 가져올 수 있다.

<script th:inline="javascript">
	console.log([[${str1}]]) //Hello
	console.log([[${str1}]] + ' ' + [[${str2}]]) //Hello World
	
	listSample = [[${listSample}]] // ['list1', 'list2']
	for(i in listSample) console.log(listSample[i])
    	
	objectSample = [[${objectSample}]] // {id : id, name : name}
	console.log(objectSample.id) //id
</script>

 

 

APPENDIX#1 환경변수 불러오기

 

application.properties 등에 설정된 환경변수는 프로그램 전반에서 사용된다. 그리고 이는 UI내에서도 사용될 수 있다.

 

만약 Thymeleaf HTML 내에서 해당 변수를 불러와야 한다면 아래와 같이 불러올 수 있다.

 

*HTML 내에서

${@environment.getProperty('환경변수명')}

 

*JS 내에서

/*[[${@environment.getProperty('환경변수명')}]]*/

 

 

APPENDIX#2 세션 내 데이터 불러오기

 

사용자 명을 가져와서 출력하는 등 세션 내 데이터를 가져오는 방법은 아래와 같다.

 

*HTML 내에서

${session.변수명}

 

*JS 내에서

[[${session.변수명}]]

 

728x90
반응형

'실습 > 리눅스 서버 + 스프링 부트' 카테고리의 다른 글

Spring Security  (0) 2021.11.07
HAProxy를 활용한 IFrame 활성화  (0) 2021.09.26
09. MariaDB CRUD_UI  (0) 2021.09.18
08. HAProxy  (0) 2021.05.30
07. Kafka_Pub&Con  (0) 2021.05.30