주로 Spring Framework와 함께 사용되며, 서버 측에서 데이터를 바인딩하고 렌더링하기 때문에 개발 단계에서 백엔드 개발자들이 쉽게 확인할 수 있다. 이로 인해 백엔드 개발자가 서버 응답을 가볍게 확인하거나 디버깅할 때 유용하게 활용된다.
웹 브라우져에서 JSP로 구성된 파일을 연다면 정상적인 결과를 확인할수 없지만, 타임리프를 활용하면 HTML 마크업 결과가 어떻게 되는지 파일만 열어도 확인 가능하다. 이렇게 순수 HTML을 그대로 유지하면서 뷰 템플릿도 사용할 수 있는 타임리프의 특징을 네츄럴 템플릿(natural templates)이라 한다.
타임리프는 스프링과 자연스럽게 통합되고 스프링의 다양한 기능을 편리하게 사용할 수 있게 지원한다.
Controller에서 Http 요청을 수신하면, Model의 addAttribute 메서드를 사용하여 동적으로 데이터를 추가한다. 이후 타임리프 템플릿 엔진이 해당 데이터를 사용해 서버 측에서 HTML 템플릿을 렌더링하고, 완성된 HTML 페이지를 클라이언트에게 반환한다.
컨트롤러
@Controller
@RequestMapping("/basic")
public class BasicController {
@GetMapping("/text-basic")
public String textBasic(Model model) {
model.addAttribute("data", "Hello Spring!");
return "basic/text-basic";
}
}
템플릿 코드
<li>th:text 사용<span th:text="${data}"> </span></li>
<li>컨텐츠 안에서 직접 출력하기 [[${data]}]</li>
HTML 페이지 원본
Note) 만약 모델에 HTML문법을 사용하고 싶어 태그(부등호)를 모델에 바인딩하면 HTML문법 적용이 안되고 태그 그자체가 반환된다. 소스보기를 하면 부등호는 앤퍼센트lt로 보인다. 이렇게 HTML에서 사용하는 특수 문자를 HTML 엔티티로 변경하는 것을 이스케이프(escape)라고 한다.
바인딩 데이터에 태그를 함께 렌더링 할때 unescape 문법을 사용한다.
템플릿 코드
<li>th:text = <span th:text="${data}"></span></li>
<li>th:utext = <span th:utext="${data}"></span></li>
<!--생략-->
<li><span th:inline="none">[[...]] = </span>[[${data}]]</li>
<li><span th:inline="none">[(...)] = </span>[(${data})]</li></li>
HTML 페이지 원본
타임리프에서 이스케이프 처리를 기본으로 적용하는 이유는, 이스케이프 처리가 없이 게시물 내용을 확인하는 순간 HTML 태그가 그대로 실행되어 페이지가 깨지거나 악성 스크립트가 실행될 수 있어 보안상 문제가 발생할 수 있다.
HTML 태그 속성이 아니라 콘텐츠 영역 안에서 직접 데이터를 출력하고 싶으면 [[${data}]]를 사용하면 된다.
스프링에서 객체에 접근하는 문법를 타임리프에서 사용한다. 여러가지 방법으로 Object,List,Map 자료구조에 접근해서 렌더링이 가능하다.
컨트롤러
@GetMapping("/variable")
public String variable(Model model){
User userA = new User("userA", 10);
User userB = new User("userB", 20);
List<User> list=new ArrayList<>();
list.add(userA);
list.add(userB);
Map<String,User> map=new HashMap<>();
map.put("userA",userA);
map.put("userB",userB);
model.addAttribute("user",userA);
model.addAttribute("users",list);
model.addAttribute("userMap",map);
return "basic/variable";
}
템플릿 코드
Object
<li>${user['username']} = <span th:text="${user['username']}"></span></li>
<li>${user.getUsername()} = <span th:text="${user.getUsername()}"></span></li>
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>
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>
HTML 페이지 원본
모든 태그 동일하게 보여진다.
타임리프는 스프링 3.0부터 HttpServletRequest, HttpServletResponse, HttpSession, ServletContext와 같은 기본 객체들을 템플릿에서 바로 사용할 수 없게 되었다. 이를 해결하기 위해 컨트롤러에서 Model 객체를 사용하여 직접 이 객체들을 템플릿에 넘겨주어야 한다.
@GetMapping("/basic-objects")
public String basicObjects(Model model, HttpServletRequest request,
HttpServletResponse response, HttpSession session) {
session.setAttribute("sessionData", "Hello Session");
model.addAttribute("request", request);
model.addAttribute("response", response);
model.addAttribute("servletContext", request.getServletContext());
return "basic/basic-objects";
}
타임리프 편의 객체들
타임리프는 param과 session 같은 편의 객체를 제공하여 기본 객체들을 더 쉽게 다룰 수 있다. param과 session을 통해 HTTP 요청 파라미터와 세션 속성에 바로 접근할 수 있어 코드를 간결하게 유지할 수 있다.
<li>Request Parameter = <span th:text="${param.paramData}"></span></li>
<li>session = <span th:text="${session.sessionData}"></span></li>
<li>spring bean = <span th:text="${@helloBean.hello('Spring!')}"></span></li>
Thymeleaf -2에 계속..