백오피스 프로젝트를 진행하면서 **타임리프(Thymeleaf)**를 사용하게 되었다.
템플릿 엔진이란 무엇인지, 그리고 타임리프가 어떤 구조로 동작하는지 정리해보았다
🧩 템플릿 엔진이란?
템플릿 엔진(Template Engine) 은 서버에서 HTML을 동적으로 생성해주는 도구다. 단순히 HTML을 반환하는 것이 아니라, 서버에서 전달한 데이터를 템플릿 문법으로 바인딩하여 조건부 렌더링, 반복문, 데이터 출력 등을 가능하게 한다.
Spring Boot 환경에서는 JSP 대신 Thymeleaf 가 많이 사용된다.
💡 왜 JSP 대신 Thymeleaf를 사용할까?
JSP는 오래된 방식으로, 설정이 복잡하고 Spring Boot의 내장 톰캣 환경에서 불안정하게 동작한다.
JSP는 .jsp 파일을
→ 서블릿(.java) 로 변환
→ 컴파일 후 실행하면서 HTML을 생성
문제는 JAR 형태로 패키징된 Spring Boot 앱에서는 JSP 파일이 실제 파일 시스템이 아닌 압축된 리소스(JAR 내부) 로 존재한다는 점이다. JSP 엔진(톰캣)은 JSP 파일을 파일 경로 기반으로 접근해야 하는데, 압축된 상태에서는 이를 읽을 수 없게 되어 오류가 자주 발생한다.
즉, JAR 실행 구조와 JSP의 서블릿 변환·컴파일 메커니즘이 맞지 않다. 반면, Thymeleaf는 HTML을 파싱해서 서버 데이터를 바인딩하는 구조라 파일 시스템 접근 없이도 문제없이 작동한다.
정리:
- 타임리프는
- html 친화적 템플릿으로 레이아웃 프래그먼트 재사용이 가능함
- Spring과 자연스럽게 연동 (Model, Security, Validation 등)
- JSP는
- 복잡한 설정: JSP는 내장 톰캣(Tomcat) 환경에서 동작이 불안정하고, jar 패키징 시 제대로 렌더링되지 않는 경우가 있다고 함
구조와 동작 방식
1. 의존성 설정 (build.gradle)
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
- spring-boot-starter-thymeleaf: 타임리프 기본 엔진
- thymeleaf-layout-dialect: 레이아웃 기능 (템플릿 조합)
- thymeleaf-extras-springsecurity6: Spring Security 통합
2. 타임리프 설정 (application.yml)**application.yml
thymeleaf:
cache: false
prefix: classpath:/templates/
mode: HTML
encoding: UTF-8
- cache: false: 개발 시 템플릿 캐시 비활성화
- prefix: classpath:/templates/: 템플릿 파일 위치
- mode: HTML: HTML 모드로 동작
- encoding: UTF-8: UTF-8 인코딩
3. 컨트롤러에서 뷰 반환
@GetMapping (value = "/main/dashboard")
public String main(Model model, HttpServletRequest req, HttpServletResponse res) {
return "pages/main/dashboard";
}
- 컨트롤러 메서드가 문자열을 반환하면 타임리프가 해당 템플릿을 찾음
- "pages/main/dashboard" → classpath:/templates/pages/main/dashboard.html
4.템플릿 구조
html인데 타임리프 문법적인게 포함된다.
<!DOCTYPE html>
<html lang="ko"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
>
- xmlns:th: 타임리프 네임스페이스
- xmlns:layout: 레이아웃 다이얼렉트 네임스페이스
페이지 템플릿(login.html)
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layouts/single_layout}">
• layout:decorate="~{layouts/single_layout}": 레이아웃 템플릿 사용
타임리프 주요 기능들
실제 프로젝트에서 사용한 기능들은 다음과 같다.
1.Fragment 사용
<th:block th:replace="~{fragments/common_include :: common-css}"></th:block>
<th:block layout:fragment="css"></th:block>
- th:replace: 다른 템플릿의 fragment를 가져와서 교체
- layout:fragment: 레이아웃에서 사용할 수 있는 영역 정의
2. URL 생성
<h6><a th:href="@{/admin-view/login/resetPwd}">비밀번호 재발급</a><a th:href="@{/admin-view/login/joinTerms}">회원가입</a></h6>
• th:href="@{...}": URL을 동적으로 생성
3. 데이터 바인딩
<form id="loginCertForm" th:object="${loginRequest}" onsubmit="return false;">
<input th:field="*{authMobileNo}" class="txt-type-normal" placeholder="인증번호를 입력해 주세요.">
- th:object="${loginRequest}": 폼 객체 바인딩
- ${...}: 서버에서 전달된 데이터 참조
4. 자바스크립트 변수 주입
<script th:inline="javascript">
state.rootPath = /*[[${@appProps.getWebRootPath()}]]*/ "/admin-view";
/* 메뉴 권한 관련된 */
state.menuAuth = {
gnbSeq: /*[[${gnbSeq}]]*/ "",
lnbSeq: /*[[${lnbSeq}]]*/ "",
authMenuCode: /*[[${authMenuCode}]]*/ ""
};
</script>
• th:inline="javascript": JavaScript에 서버 데이터 주입
동작 흐름 정리
- 요청 처리: 사용자가 URL 접근 (/admin-view/login)
- 컨트롤러 실행: LoginController.getLogin() 메서드 실행
- 모델 데이터 추가: model.addAttribute("newPwdRequest", new NewPwdRequest())
- 뷰 이름 반환: "pages/login/login"
- 템플릿 해석: 타임리프가 templates/pages/login/login.html 찾음
- 레이아웃 적용: layout:decorate="~{layouts/single_layout}"로 레이아웃 적용
- Fragment 처리: th:replace로 공통 요소들 삽입
- 데이터 바인딩: ${...}, *{...} 표현식으로 데이터 렌더링
- HTML 생성: 최종 HTML 생성하여 브라우저에 전송
핵심 개념
- 템플릿 엔진: 서버에서 HTML을 동적으로 생성
- Fragment: 재사용 가능한 템플릿 조각
- Layout: 전체 페이지 구조를 정의하는 템플릿
- 데이터 바인딩: 서버 데이터를 HTML에 연결
- 표현식: ${...}, *{...}, @{...} 등으로 데이터 참조
'Dev Log' 카테고리의 다른 글
| Spring + MyBatis 기반 개인정보 암호화/복호화 과정 정리 (0) | 2025.11.02 |
|---|---|
| SQL 기본 개념 정리2 (0) | 2025.10.26 |
| Postman + OpenAPI로 타입 체크되는 API 만들기 (0) | 2025.10.12 |
| React Hook Form 활용기 (0) | 2025.10.05 |
| 백오피스 파일 수정 디버깅 과정 (0) | 2025.09.28 |