부트 개념과 활용-18.Thymeleaf
스프링 웹 MVC 7부: Thymeleaf
스프링 부트가 자동 설정을 지원하는 템플릿 엔진
- FreeMarker
- Groovy
- Thymeleaf
- Mustache
JSP는 없다.(자동설정 미지원, 권장하지도 않는다.)
JSP를 권장하지 않는 이유
스프링 부트는 임베디드 톰캣으로 애플리케이션을 빠르고 쉽게 만들어 배포하길 원한다.
JAR 패키징 할 때는 동작하지 않고, WAR 패키징 해야 함. (물론 war로 패키징 하더라도 실행은 가능하다.)
Undertow는 JSP를 지원하지 않음.
https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-jsp-limitations
Thymeleaf 사용하기
https://www.thymeleaf.org/
https://www.thymeleaf.org/doc/articles/standarddialect5minutes.html
의존성 추가: spring-boot-starter-thymeleaf
템플릿 파일 위치: /src/main/resources/template/
예제: https://github.com/thymeleaf/thymeleafexamples-stsm/blob/3.0-master/src/main/webapp/WEB-INF/templates/seedstartermng.html
예제코드
@ExtendWith(SpringExtension.class) // junit 5 기준
@WebMvcTest(SampleController.class)
class SampleControllerTest {
@Autowired
MockMvc mockMvc;
@Test
public void hello() throws Exception {
// 요청 "hello"
// 응답
// - 모델 name : jaeuk
// - 뷰 이름 : hello
mockMvc.perform(get("/hello"))
.andExpect(status().isOk())
.andDo(print()) // 렌더링된 결과를 확인 가능
.andExpect(view().name("hello"))
.andExpect(model().attribute("name", "jaeuk")); // junit 5 기준
}
}
@Controller
public class SampleController {
@GetMapping("/hello")
public String hello(Model model){
model.addAttribute("name", "jaeuk");
return "hello"; // hello view name 리턴
}
}
templete -> hello.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<!-- 타임리프 사용하려면 html 문서에 선언 xmlns:th="http://www.thymeleaf.org" -->
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1 th:text="${name}"> null name jaeuk </h1>
<!-- name 값 전달되면 전달된 값 없으면 null name jaeuk -->
</body>
</html>
출력결과
MockHttpServletRequest:
HTTP Method = GET
Request URI = /hello
Parameters = {}
Headers = []
Body = <no character encoding set>
Session Attrs = {}
Handler:
Type = me.jaeuk.thymeleaf.SampleController
Method = me.jaeuk.thymeleaf.SampleController#hello(Model)
Async:
Async started = false
Async result = null
Resolved Exception:
Type = null
ModelAndView:
View name = hello
View = null
Attribute = name
value = jaeuk
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 200
Error message = null
Headers = [Content-Language:"en", Content-Type:"text/html;charset=UTF-8"]
Content type = text/html;charset=UTF-8
Body = <!DOCTYPE html>
<html lang="en">
<!-- 타임리프 사용하려면 html 문서에 선언 xmlns:th="http://www.thymeleaf.org" -->
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>jaeuk</h1>
<!-- name 값 전달되면 전달된 값 없으면 null name jaeuk -->
</body>
</html>
Forwarded URL = null
Redirected URL = null
Cookies = []
andDo.(print()) 렌더링된 결과를 확인 가능 타임리프를 쓰니까 가능한 것.
JSP를 사용할 땐 렌더링 한 결과를 확인하기 힘들다.
서블릿 엔진이 개입을 해야만(서블릿 엔진이 만들어 내야만..) 응답을 내보낼 최종적인 뷰를 확인할 수 있다.
근데 타임리프는 독자적으로 최정적인 뷰를 완성한다.
서블릿 컨테이너의 개입 없이,
WebMvcTest는 서블릿 컨테이너를 띄우는게 아니다. (가짜 서블릿 컨테이너) - 서블릿 컨테이너의 역할 못 함 즉, JSP를 렌더링 시켜서 확인 못한다.
하지만 타임리프는 서블릿 컨테이너에 독립적인 엔진이라 뷰에 렌더링되는 결과까지도 확인이 가능.
출력 결과 jaeuk 확인.
더 자세한 내용은 위의 타임리프 문서 참조.