템플릿 엔진
- 지정된 템플릿 양식과 데이터가 합쳐져 HTML 문서를 출력하는 소프트웨어를 이야기한다.
서버 템플릿 엔진
- JSP(Spring JSP), Freemarker
- 서버 템플릿 엔진은 서버에서 구동된다.
서버에서 Java 코드로 문자열을 만든 뒤 이 문자열을 HTML 로 변환하여 브라우저로 전달한다.
- 이때 자바 스크립트 코드는 단순한 문자열이다.
- 이게 브라우저에서 작동하게 되면 그때는 서버 템플릿 엔진의 손을 벗어나 제어할 수 없다.
클라이언트 템플릿 엔진
- React, Vue
- 서버에서 이미 코드가 벗어난 경우이다.
- JSON, XML 형식의 데이터만 전달하고 클라이언트에서 조립한다.
그러면 Mustach는 무슨 템플릿 엔진인가?
- 수많은 언어를 지원하는 가장 심플한 템플릿 엔진
- 다른 엔진에 비해 문법이 심플하다.
- 로직 코드를 사용할 수 없어 View의 역할과 서버의 역할이 명확하게 분리된다.
- Mustache.js, Mustacje.java 2가지나 다 있어, 하나의 문법으로 클라이언트/서버 템플릿 모두 사용 가능
실습
- 컨트롤러에서 반환되는 값을 경로가 되어 URL을 매핑한다.
index.mustache
{{>layout/header}}
<h1>스프링부트로 시작하는 웹 서비스 v1.0.5</h1>
<div class="col-md-12">
<div class="row">
<div class="col-md-6">
<a href="/posts/save" role="button" class="btn btn-primary">글 등록</a>
{{#userName}}
Logged in as: <span id="user">{{userName}}</span>
<a href="/logout" class="btn btn-info active" role="button">Logout</a>
{{/userName}}
{{^userName}}
<a href="/oauth2/authorization/google" class="btn btn-success active" role="button">Google Login</a>
<a href="/oauth2/authorization/naver" class="btn btn-secondary active" role="button">Naver Login</a>
{{/userName}}
</div>
</div>
<br>
<table class="table table-horizontal table-bordered">
<thead class="thead-strong">
<tr>
<th>게시글번호</th>
<th>제목</th>
<th>작성자</th>
<th>최종수정일</th>
</tr>
</thead>
<tbody id="tbody">
{{#posts}}
<tr>
<td>{{id}}</td>
<td><a href="/posts/update/{{id}}">{{title}}</a></td>
<td>{{author}}</td>
<td>{{modifiedDate}}</td>
</tr>
{{/posts}}
</tbody>
</table>
</div>
{{>layout/footer}}
<!DOCTYPE HTML>
<html>
<head>
<title>스프링부트 웹서비스</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script src="/js/app/index.js"></script>
</body>
</html>
테스트 코드
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
public class IndexControllerTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
public void 메인페이지_로딩() {
String body = this.restTemplate.getForObject("/", String.class);
assertThat(body).contains("스프링부트로 시작하는 웹 서비스");
}
}