
Thymeleaf
스프링부트의 공식 View를 보여주는 서버 사이드 템플릿 엔진
주요 문법
HTML 태그 안에 붙여 사용한다
전달한 모델의 어트리뷰트는 ${} 로 감싸 꺼낸다
th:text, th:utext, [[…]]
// 일반 텍스트 출력 <p th:text="${user.name}">홍길동</p> // 만약 부가적인 HTML 태그를 붙여 출력하는 경우에 사용함 <p th:utext="${htmlContent}">내용</p> // 인라인 표현 <p>이름: [[${user.name}]]</p>th:href, th:src
<!-- URL --> <a th:href="@{/users/{id}(id=${user.id})}">상세보기</a> <!-- 결과: <a href="/users/1">상세보기</a> --> <!-- 쿼리 파라미터 --> <a th:href="@{/search(keyword=${keyword}, page=1)}">검색</a> <!-- 결과: <a href="/search?keyword=spring&page=1">검색</a> --> <!-- 이미지 --> <img th:src="@{/images/product/{id}.jpg(id=${product.id})}" /> <!-- 결과: <img src="/images/product/123.jpg" /> -->th:class, th:style, th:attr
<!-- 조건부 클래스 --> <div th:class="${user.active} ? 'active' : 'inactive'">상태</div> <!-- 여러 클래스 --> <div th:classappend="${user.vip} ? 'vip-badge' : ''">사용자</div> <!-- 스타일 --> <span th:style="'color:' + ${product.stock > 0 ? 'green' : 'red'}"> 재고 </span> <!-- 모든 속성 설정 가능 --> <input type="text" th:attr="value=${user.name}, placeholder='이름 입력'" /> <!-- 또는 개별 지정 (더 간단) --> <input type="text" th:value="${user.name}" th:placeholder="'이름 입력'" />th:each
<!-- 기본 --> <div th:each="user : ${users}"> <p th:text="${user.name}">이름</p> </div> <!-- 인덱스 사용 --> <tr th:each="product, stat : ${products}"> <td th:text="${stat.index}">0</td> <!-- 0부터 시작 --> <td th:text="${stat.count}">1</td> <!-- 1부터 시작 --> <td th:text="${product.name}">상품명</td> </tr> <!-- stat 정보 --> <!-- stat.index: 0부터 시작하는 인덱스 --> <!-- stat.count: 1부터 시작하는 카운트 --> <!-- stat.size: 전체 개수 --> <!-- stat.first: 첫 번째인지 (boolean) --> <!-- stat.last: 마지막인지 (boolean) --> <!-- stat.even: 짝수인지 (boolean) --> <!-- stat.odd: 홀수인지 (boolean) -->th:if, th:unless, th:switch, th:case
<!-- if (조건이 true일 때) --> <div th:if="${user.age >= 18}"> <p>성인입니다</p> </div> <!-- unless (조건이 false일 때) --> <div th:unless="${user.active}"> <p>비활성 사용자입니다</p> </div> <!-- 빈 값 체크 --> <p th:if="${not #strings.isEmpty(user.email)}"> 이메일: [[${user.email}]] </p> <!-- null 체크 --> <div th:if="${product != null}"> <p th:text="${product.name}">상품명</p> </div> <div th:switch="${user.role}"> <p th:case="'ADMIN'">관리자</p> <p th:case="'USER'">일반 사용자</p> <p th:case="'GUEST'">게스트</p> <p th:case="*">기타</p> <!-- default --> </div> <!-- 상품 상태 표시 --> <span th:switch="${product.status}"> <span th:case="'AVAILABLE'" class="badge-success">판매중</span> <span th:case="'SOLD_OUT'" class="badge-danger">품절</span> <span th:case="'DISCONTINUED'" class="badge-warning">단종</span> </span>@{…}
<!-- 기본 URL --> <a th:href="@{/users}">사용자 목록</a> <!-- 경로 변수 --> <a th:href="@{/users/{id}(id=${user.id})}">상세보기</a> <!-- 결과: /users/123 --> <!-- 여러 경로 변수 --> <a th:href="@{/users/{userId}/orders/{orderId}(userId=${user.id}, orderId=${order.id})}"> 주문 상세 </a> <!-- 결과: /users/123/orders/456 --> <!-- 쿼리 파라미터 --> <a th:href="@{/search(keyword=${keyword}, page=${page})}">검색</a> <!-- 결과: /search?keyword=spring&page=1 --> <!-- 경로 변수 + 쿼리 파라미터 --> <a th:href="@{/products/{id}(id=${product.id}, view='detail')}">상품</a> <!-- 결과: /products/123?view=detail -->
Share article