SSR(Server Side Rendering)/Thymeleaf

Thymeleaf[타임리프]란? 타임리프의 기본 기능(표현식, escape, 스프링EL, 변수 선언)

녁이 2023. 12. 12. 02:57
728x90
반응형

타임리프(Thymeleaf)란?

- 타임리프는 백엔드 서버에서 HTML을 동적으로 렌더링 하는 용도로 사용되는 템플릿 엔진이다.

( 백엔드 서버에서 동적으로 렌더링 한다는 말은 타임 리프가 서버 사이드 HTML 렌더링(SSR) 중 하나라는 걸 뜻한다. )

 

SSR에는 타임리프를 제외하고, JSP, FreeMarker, Velocity 등이 있는데, 스프링을 사용하는 한, 스프링을 통합 지원해주는 타임리프가 1순위라고 생각한다.


타임리프(Thymeleaf)의 특징

  • 서버 사이드 HTML 렌더링(SSR)
  • 네츄럴 템플릿
  • 스프링 통합 지원

여기서 네츄럴 템플릿이란?

순수 HTML을 최대한 유지하려는 타임리프의 특징이다.

타임리프로 작성한 파일은 HTML을 유지하기 때문에 웹 브라우저에서 파일을 직접 열어도 내용을 확인할 수 있고, 서버를 통해 뷰 템플릿을 거치면 동적으로 변경된 결과를 확인할 수 있다.

이렇게 순수 HTML을 그대로 유지하면서 뷰 템플릿도 사용할 수 있는 타임리프의 특징을 네츄럴 템플릿이라고 한다.

 


타임리프를 사용하려면?

해당 프로젝트를 생성할 때 Gradle에 Thymeleaf를 추가해주야 한다. 

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-tymeleaf'
...
}

build.gradle에 위와 같이 선언되어 있나 확인해보도록 하자.

 

또한,

타임리프를 사용할 HTML 파일에서 타임리프 사용 선언을 해주어야 한다.

<html> 부분을 아래와 같이 바꿔주면 끝이다.

<html xmlns:th="http://www.thymeleaf.org">

 


타임리프 기본 표현식

기본 표현식들은 위의 사진과 같은데, 더 자세하고 많은 내용은 아래 차차 풀어보겠다.

 


텍스트 - text, utext

텍스트를 출력하는 기능

 

타임리프는 기본적으로 HTML 테그의 속성에 기능을 정의해서 동작한다.

때문에, HTML의 컨텐츠에 데이터를 출력할 때는 아래의 형식을 따르면 된다.

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

 

해당 테그를 사용하지 않고 HTML 컨텐츠 영역 안에서 직접 데이터를 출력하고 싶다면, 아래와 같은 형식을 따라보자.

컨텐츠 안에서 직접 출력하기 = [[${data}]]

여기서 data는 컨트롤러에서 model에 담아 넘겨주는 데이터의 이름이다.

 

 

Ex)

<h1>컨텐츠에 데이터 출력하기</h1>
<ul>
 <li>th:text 사용 <span th:text="${data}"></span></li>
 <li>컨텐츠 안에서 직접 출력하기 = [[${data}]]</li>
</ul>

 


Escape

HTML 문서는 <, > 와 같은 특수 문자를 기반으로 정의된다. 따라서 뷰 템플릿으로 HTML 화면을 생성할 때는 이러한 특수 문자를 주의해야 한다.

 

만약에 위의 예시에 data 값으로 "Hello <b>Spring!</b>" 를 넘긴다면 어떻게 될까?

여기서 <b>테그를 사용함으로써, Spring! 단어를 진하게 나오도록 하고 싶은 것이다.

→ 웹 브라우저에서 실행 결과를 보면,

Hello &lt;b&gt;Spring!&lt;/b&gt;

이렇게 나온다.

<와 /> 부분이 다 바뀐 것이다.

 

HTML 엔티티

웹 브라우저는 < 를 HTML 테그의 시작으로 인식한다. 따라서 < 를 문자로 표현할 방법이 필요한데, 이것을 HTML 엔티티라고 한다. 이렇게 HTML에서 사용하는 특수 문자를 HTML 엔티티로 변경하는 것을 이스케이프(escape)라고 한다.

( 위에서 설명한 th:text, [[...]] 형식은 기본적으로 escape를 지원함 )

 

 

만약 위에 나의 바램처럼 이스케이프를 사용하지 않고, <b>테그를 적용시키려면 어떻게 해야 할까?

Unescape

타임리프는 다음 두 기능을 제공한다.

  • th:text → th:utext
  • [[...]] [(...)]

 

Ex)

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

<li><span th:inline="none">[(...)] = </span>[(${data})]</li>

 

th:inline="none" : 타임리프는 [[...]] 를 해석하기 때문에, 화면에 [[...]] 글자를 보여줄 수 없다.

이 테그 안에서는 타임리프가 해석하지 말라는 옵션이다.

 

해당 형식들을 사용하면 이스케이프 기능을 사용하지 않을 수 있고, <b>테그를 사용할 수 있다.

하지만 실무에서는 escape 기능은 거의 사용한다고 볼 수 있다. 왜냐하면, 사용자들이 여러 특수 문자들을 많이 기입하고 하기 때문에 에러가 발생할 수 있기 때문이다.

이스케이프 기능을 사용하는게 기본! 필요시에만 Unescape!


변수 - SpringEL

타임리프에서 변수를 사용할 때에는 아래의 변수 표현식을 사용한다.

${...}

해당 표현식에는 스프링 EL이라는 스프링이 제공하는 표현식을 사용할 수 있다.

 

 

User이라는 class를 만들고, username, age를 통해 생성자를 만들어 준다.

List<User>, Map<String,User> 등에 userA, userB를 만들어서 넣어주고, 이를 model에 담아서 넘겨준다.

 

 

HTML 파일

<html xmlns:th="http://www.thymeleaf.org">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>
<h1>SpringEL 표현식</h1>
<ul>Object
 <li>${user.username} = <span th:text="${user.username}"></span></li>
 <li>${user['username']} = <span th:text="${user['username']}"></span></li>
 <li>${user.getUsername()} = <span th:text="${user.getUsername()}"></span></li>
</ul>
<ul>List
 <li>${users[0].username} = <span th:text="${users[0].username}"></span></li>
 <li>${users[0]['username']} = <span th:text="${users[0]['username']}"></span></li>
 <li>${users[0].getUsername()} = <span th:text="${users[0].getUsername()}"></span></li>
</ul>
<ul>Map
 <li>${userMap['userA'].username} = <span th:text="${userMap['userA'].username}"></span></li>
 <li>${userMap['userA']['username']} = <span th:text="${userMap['userA']['username']}"></span></li>
 <li>${userMap['userA'].getUsername()} = <span th:text="${userMap['userA'].getUsername()}"></span></li>
</ul>
</body>
</html>

 

Object, List, Map에 따른 다양한 표현식을 사용했다.

자바빈 프로퍼티 접근법을 사용한다.

 

전부, userA라는 것을 출력하게끔 만들었다.

Object는 간단하게 프로퍼티 접근으로 user.username을 사용했다. 이는, user.getUsername() 메서드와 같다고 보면 된다.

List에서는 users[index].username 등을 사용해 index를 기입하여 그 값을 추출했다.

Map에서는 userMap['key'].username 등을 사용해 맵의 key값을 넣어 그 값을 추출했다.

 

지역 변수 선언

자바와 같이 지역 변수를 선언해서 사용할 수도 있다.

th:with 을 사용하면 지역 변수를 선언해서 사용할 수 있다. 해당 지역 변수는 선언한 테그 내에서만 사용이 가능.

 

<h1>지역 변수 - (th:with)</h1>
<div th:with="first=${users[0]}">
 <p>처음 사람의 이름은 <span th:text="${first.username}"></span></p>
</div>

 

코드를 보면, th:with 으로 시작했고, first 변수에 users List의 첫번째 user 객체를 할당했다.

그리고 first.username을 통해 userA 라는 값이 출력된다.

→ 출력 결과 : 처음 사람의 이름은 userA

first라는 변수는 <div> </div> 테그 내에서만 사용이 가능하다. 

 


다음 게시글

글의 분량을 나누기 위해 해당 게시글은 여기까지.. 다음 게시글에 타임 리프에 더 자세한 내용들을 적도록 하겠다.

예를 들어, 타임리프에서 Http 요청 파라미터에 접근, Http 세션에 접근 등과 타임리프의 유틸리티 객체들 등을 말하고 타임리프에서 URL 링크를 어떻게 처리하는지 등을 설명하겠다.

 

 

728x90
반응형