반복문으로 list에 저장된 값을 HTML에서도 부를 수 있다는 강점이 있음.

 

<tr th:each="user : ${users}">

구조는 java의 향상된 for 문과 얼추 비슷하다.  user(임의 변수 지정) 에 {users}(자바의 리스트가 담긴 변수) 를 꺼내서 반복해!

 

처리가능한 반복조건은 ,Iterable, Enum,Map, 등등 다양하다.

발췌 : https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html#using-theach

<tr>
    <th>이름</th>
    <th>나이</th>
</tr>
//연속된 데이터를 불러올 수 있다. 
<tr th:each="user : ${users}">
    <td th:text="${user.username}">username</td>
    <td th:text="${user.age}">0</td>
</tr>

위와 같이 'user.username' 과 'uer.age' 한번 작성했지만, 아래 코드와 같이 실행결과는 user ,A,B,C 모두를 불러왔다. 

<tr>
    <th>이름</th>
    <th>나이</th>
</tr>
<tr>
    <td>userA</td>
    <td>10</td>
</tr>
<tr>
    <td>userB</td>
    <td>20</td>
</tr>
<tr>
    <td>userC</td>
    <td>30</td>
</tr>

 

 

 

 


 

조건문

<!-- user.age를 가져와서 출력하되 없으면 출력하지않음 -->
<span th:text="${user.age}">0</span>

<!-- user.age 가 20보다 "<"작으면(lt='<') 미성년자를 찍어주고, 조건이 false가 되면
   해당 태그를 아예 없는셈 친다. -->
<span th:text="'미성년자'" th:if="${user.age lt 20}">성인</span>

<!-- user.age 가 20보다 ">" 크면(ge='>') 해당 태그를 없는셈 쳐버리고, 조건이 false가 되면
   즉 , 작으면 미성년자를 찍어준다. -->
<span th:text="'미성년자'" th:unless="${user.age ge 20}">성인</span>

태그 가운데, if, unless 로 작업된다.

 

그래서 만약 나이가 20세라 가정하면 

20
(if false → 출력 안 됨)
(unless false → 출력 안 됨)

 

나이가 15세라 가정하면

15
미성년자
미성년자

 

요래 출력된다. 

 

참고로 연산자는 아래와 같음

lt less than <
le less or equal <=
gt greater than >
ge greater or equal >=
eq equal ==
ne not equal !=

 

🌿 타임리프(Thymeleaf) 핵심 1페이지 요약

스프링 MVC에서 뷰 렌더링할 때 필요한 필수 기능만 모음.
CRUD 프로젝트 화면 구현 시 이거면 충분!


1️⃣ 변수/객체 접근

<!-- 단일 객체 -->
<span th:text="${user.username}"></span>
<span th:text="${user['username']}"></span>
<span th:text="${user.getUsername()}"></span>

<!-- 리스트 접근 -->
<span th:text="${userList[0].username}"></span>

<!-- 맵(Map) 접근 -->
<span th:text="${userMap['userA'].username}"></span>

✅ 3가지 방식 모두 같은 결과
. = 프로퍼티 접근, ['key'] = Map key 접근, getXxx() = Getter 호출


2️⃣ 반복 & 조건

<!-- 반복 -->
<tr th:each="user, stat : ${userList}">
    <td th:text="${stat.index}"></td>      <!-- 0부터 시작 -->
    <td th:text="${user.username}"></td>
</tr>

<!-- 조건 -->
<p th:if="${user.age >= 20}">성인</p>
<p th:unless="${user.age >= 20}">미성년자</p>

🔹 th:each="item, stat : ${리스트}"
보조변수(stat) → index, count, first, last 등 사용 가능


3️⃣ 속성 처리 (URL, 클래스 등)

<!-- 링크 -->
<a th:href="@{/users/{id}(id=${user.id})}">상세보기</a>
<!-- 결과: /users/1 -->

<!-- 경로 + 쿼리 -->
<a th:href="@{/users/{id}(id=${user.id}, sort='desc')}"></a>
<!-- 결과: /users/1?sort=desc -->

<!-- 클래스 동적 추가 -->
<div th:classappend="${user.active} ? 'on' : 'off'"></div>

4️⃣ 템플릿 조각 & 레이아웃

<!-- fragment.html -->
<footer th:fragment="footer">
  <p>Copyright 2025</p>
</footer>

<!-- 삽입 -->
<div th:insert="template/fragment :: footer"></div>
<!-- div 유지 + footer 내용 삽입 -->

<!-- 교체 -->
<div th:replace="template/fragment :: footer"></div>
<!-- div 사라지고 footer 태그로 교체 -->

5️⃣ 주석 처리

<!-- 표준 HTML 주석: 항상 렌더링 -->
<!-- 이 코멘트는 페이지 소스에 보임 -->

<!--/* 타임리프 주석: 렌더링 시 사라짐 */-->
<!--/* [[${user.username}]] */-->

✅ 최종 요약

  1. 데이터 출력${}, ., [], getXxx()
  2. 반복 & 조건th:each, th:if / th:unless
  3. 속성 처리th:href, th:src, th:classappend
  4. 레이아웃th:fragment + insert / replace
  5. 주석 처리<!--/* ... */-->

이 5가지만 기억하면 CRUD 웹 화면 구현 90% 가능

 

자바에서 3가지 유형으로 user를 저장하고

 

model.addAttribute("user", user);
model.addAttribute("userList", list);
model.addAttribute("userMap", map);

Model 객체에 "user" 에 1명의 user를 저장 , list, map 에 각각 데이터를 저장한후 thymeleaf에서 불러오려면

 

//User 객체를 불러오는 프로퍼티 접근법 _ 아래 3처리방법 모두 동일한 결과 
th:text="${user.username}"
th:text="${user['username']}"
th:text="${user.getUsername()}"


//UserList 에서 0번째 객체를 불러오는 프로퍼티 접근법 _ 아래 3처리방법 모두 동일한 결과
th:text="${userList[0].username}"
th:text="${userList[0]['username']}"
th:text="${userList[0].getUsername()}"


//UserMap 에서 key를 통해서 value를 불러오는 프로퍼티 접근법 _ 아래 3처리방법은 모두 동일 결과 
th:text="${userMap['userA'].username}"
th:text="${userMap['userA']['username']}"
th:text="${userMap['userA'].getUsername()}"

 

 

 

날짜 또한 표현 가능하다. 

 

 

 

 

우선 컨트롤러에 날짜를 출력할수있도록 하고

model.addAttribute("localDateTime", LocalDateTime.now());

 

 

기본 출력과, 포맷을 설정해서 출력 가능함 

 

//기본출력
th:text="${localDateTime}"  


// yyyy-MM-dd HH:mm:ss 형식  출력 
th:text="${#temporals.format(localDateTime, 'yyyy-MM-dd HH:mm:ss')}"

 

 

요렇게 출력 된다. 

 

 

링크를 표현하기위해서는 아래와 같이 처리한다 .

 

<!--- basic url 을 클릭하면 [http://localhost:8080/path] 로 이동 --->
<li><a th:href="@{/path}">basic url</a></li>

<!--- http://localhost:8080/path?param1=data1&param2=data2 로 이동 
`()` 에 있는 부분은 쿼리 파라미터로 처리 --->
<li><a th:href="@{/path(param1=${param1}, param2=${param2})}">path query param</a></li>

<!---  http://localhost:8080/path/data1/data2  로 이동 
 '()' 내부의 param1, param2 가 각각의 경로변수에 대입처리됨 --->
<li><a th:href="@{/path/{param1}/{param2}(param1=${param1}, param2=${param2})}">path variable</a></li>

<!---  http://localhost:8080/hello/data1?param2=data2 로 이동
  {param1} 의 경로변수가 1개이므로, '()' 안의 왼쪽 param1 은 data1로 치환되고, 남은 'param2=?${param2} 는 쿼리 파라미터 형태로 변환되어 뒤에 붙어버림  
   즉 : path/data1?param2=data2" 가 된다. --->
<li><a th:href="@{/path/{param1}(param1=${param1}, param2=${param2})}">path variable + query parameter</a></li>

 

 

'Thymeleaf' 카테고리의 다른 글

4. Thymeleaf 반복, 조건, 주석  (1) 2025.08.06
Thymeleaf 핵심 요약  (0) 2025.08.05
2. Thymeleaf - text, utext 를 공부  (4) 2025.08.05
1. Thymeleaf 가 뭔지 배워야 겠다.  (2) 2025.08.05

 

 

타임리프 사용 선언 문구는 이렇게 시작하자 

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

 

 

여기 간단한 출력 문구를 위해서 java 코드를 작성 했다. 

    @GetMapping("/text-basic")  //localhost:8080/basic   -> 여기에 이어서 /text-basic 처리
    //총 url은 [localhost:8080/basic/text-basic
    public String textBasic(Model model) {
        //Model 인터페이스에 addAttribute 하면 ,"data" 변수에, "hello Spring!" 이라고 대입처리한다.
        model.addAttribute("data", "hello Spring!");
        return "basic/text-basic";
    }

 

요부분 주소에 맞추기 위해서 경로를 주의해야한다.

return "basic/text-basic";

 

 

이걸 html 문구에 사용하기위해서  text-basic.html 에 이렇게 작성되었다.

<!doctype html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<h1> 컨텐츠에 데이터 출력하기 </h1>
<ul>
    <!-----  model.addAttribute("data", "hello Spring!");  구문의 "data" 와 연동되는 구간
                                         "hello Spring!" 으로 ${data}를 치환한다. -->
    <li>th:text 사용><span th:text="${data}"></span></li>
    <li>컨텐츠 안에서 직접 출력하기 = [[${data}]]</li>
</ul>
</body>
</html>

 

 

 

"${data}"에 잘 대입되었다는걸 확인 및 URL주소 맞음!

 

 

다음은 html, 자바 코드간의 "<" 등의 코드문제를 처리해본다.

    // <b> 의 Html 볼드체를 인식하기위한 text 코드
    @GetMapping("/text-unescaped")
    public String textUnescaped(Model model) {
        model.addAttribute("data", "<b>hello Spring!<b>");
        return "basic/text-unescaped";
    }

 

<b> , <a> 등과같이  꺽쇠가 html에선 문법이기때문에 저걸 아래처럼 1개의 문장으로 엮으면 ,

"<"  문구를 "&lt;"로 출력해버리는 이스케이프가 발생한다.

"<b>hello Spring!<b>"

 

 

 th:text 로 처리하면 저렇게 문자열로 나오지만 실제 코드상에선 아래와 같이 처리된거다.

<li>th:text = <span>&lt;b&gt;hello Spring!&lt;b&gt;</span></li>

 

 

 

해결을 위해서 utext, [( )] 를 쓰면됨다.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>text vs utext</h1>
<ul>
    <!----- "<" 문구를 "&lt;"로 출력하고,    ">" 문구를 "&gt;" 로 출력 , 즉 이스케이프 처리 하기때문에,
    utext [(xx)] 를 통해서  "<b>hello Spring!<b>" 의  "<b>" 부분을 html로 출력하기 위해 해석하지말고 그냥 html로 인식하라고 처리-->
    <li>th:text = <span th:text="${data}"></span></li>
    <li>th:utext = <span th:utext="${data}"></span></li>
</ul>
<h1><span th:inline="none">[[...]] vs [(...)]</span></h1>
<ul>
    <li><span th:inline="none">[[...]] = </span>[[${data}]]</li>
    <li><span th:inline="none">[(...)] = </span>[(${data})]</li>
</ul>
</body>
</html>

 

 

 

음..간단한거지만 생각보다 복잡하네..
참고로 김영한님의 스프링 인강을 공부하면서 올리는내용이라 문제가있다고 오면 코드는 삭제하겠습니다.

 

 

※ 이 글은 인프런 김영한님의 '스프링 MVC 2편' 강의를 학습하며 개인적으로 정리한 내용입니다.

 

 

자바 + 스프링 을 공부하는데 html+css+java script도 거의 모르는 상황에서 뭔가를 연습한다는게 너무 어렵다.

 

별도로 인강으로 공부중인데, 위 thymeleaf를 사용하면  SSR로 작업한 결과를 눈으로 확인할수 있다는걸 배웠다.

SSR 이란단어도 처음 들었는데... 요건 아래 지피티용 정리를 남겨놓겠음.

 

🔹 SSR(Server-Side Rendering) 이란?

SSR은 Server-Side Rendering의 약자로,
웹 페이지의 HTML을 서버에서 미리 렌더링해서 브라우저에 전달하는 방식을 말한다.

🔹 동작 방식

  1. 사용자가 웹 페이지 요청
  2. 서버(Spring, Django, Node 등)에서
    • 데이터 조회(DB)
    • 서버에서 HTML 생성(렌더링)
  3. 완성된 HTML을 브라우저에 전송
  4. 브라우저는 HTML을 그대로 표시

🔹 특징

  • 초기 로딩 속도가 빠름 (브라우저가 바로 화면 표시 가능)
  • SEO(검색 최적화)에 유리 (HTML에 내용이 이미 들어있음)
  • 새 요청마다 전체 페이지를 다시 렌더링 → 페이지 이동 시 깜빡임 발생

🔹 예시

  • Spring MVC + Thymeleaf / JSP
  • PHP, Ruby on Rails 전통적인 웹 방식

 

 

뭐 복잡하게 써있지만, HTML은 정적인 컨텐츠니깐 화면 출력용이겠거니와... 싶은데

요 기능을 쓰면 

HTML에서 변수처럼 참조값도 쓰고, 반복문도 쓰고, 조건문도 쓸수있다!

난 인강으로 배울꺼고, 요내용은 차후 블로그에 남기면서 공부기록을 남길건데, 혹시 필요한 사람이 있을까봐 아래 사이트 정보를 남겨놓는다.

 

Thymeleaf 관련 

공식 사이트: https://www.thymeleaf.org/

공식 메뉴얼 - 기본 기능: https://www.thymeleaf.org/doc/tutorials/3.0/usingthymeleaf.html

공식 메뉴얼 - 스프링 통합: https://www.thymeleaf.org/doc/tutorials/3.0/thymeleafspring.html

+ Recent posts