스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - (6) 타임리프 기본기능 - 주석, 블록, 자바스크립트 인라인
인프런 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술편을 학습하고 정리한 내용 입니다.
주석
BasicController
1
2
3
4
5
@GetMapping("/comments")
public String comments(Model model) {
model.addAttribute("data", "Spring!");
return "basic/comments";
}
/resources/templates/basic/comments.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>예시</h1>
<span th:text="${data}">html data</span>
<h1>1. 표준 HTML 주석</h1>
<!--
<span th:text="${data}">html data</span>
-->
<h1>2. 타임리프 파서 주석</h1>
<!--/* [[${data}]] */-->
<!--/*-->
<span th:text="${data}">html data</span>
<!--*/-->
<h1>3. 타임리프 프로토타입 주석</h1>
<!--/*/
<span th:text="${data}">html data</span>
/*/-->
</body>
</html>
다음과 같이 만들었을 때
주석이 어떻게 나올까?

표준 HTML 주석
<!-- -->
자바스크립트의 표준 HTML 주석은 타임리프가 렌더링 하지 않고, 그대로 남겨둔다.
타임리프 파서 주석
<!--/* + 내용 + */-->
타임리프 파서 주석은 타임리프의 진짜 주석이다. 렌더링에서 주석 부분을 제거한다.
타임리프 프로토타입 주석
<!--/*/ + 내용 + /*/-->
타임리프 프로토타입은 약간 특이한데, HTML 주석에 약간의 구문을 더했다. HTML 파일을 웹 브라우저에서 그대로 열어보면 HTML 주석이기 때문에 이 부분이 웹 브라우저가 렌더링하지 않는다.
타임리프 렌더링을 거치면 이 부분이 정상 렌더링 된다.
쉽게 이야기해서 HTML 파일을 그대로 열어보면 주석 처리가 되지만, 타임리프를 렌더링 한 경우에만 보이는 기능이다.
잘 안쓸거 같긴 하다..
블록
<th:block> 은 HTML 태그가 아닌 타임리프의 유일한 자체 태그다.
BasicController
1
2
3
4
5
@GetMapping("/block")
public String block(Model model) {
addUser(model);
return "basic/block";
}
/resources/templates/basic/block.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<th:block th:each="user : ${users}">
<div>
사용자 이름1 <span th:text="${user.username}"></span>
사용자 나이1 <span th:text="${user.age}"></span>
</div>
<div>
요약 <span th:text="${user.username} + ' / ' + ${user.age}"></span>
</div>
</th:block>
</body>
</html>

타임리프의 특성 상 HTML 태그 안에 속성으로 기능을 정의해서 사용하는데, 위 예처럼 이렇게 사용하기 애매한 경우에 사용하면 된다. (div 2개를 한번에 반복해야 해서)
<th:block>은 렌더링 시 제거된다
자바스크립트 인라인
타임리프는 자바스크립트에서 타임리프를 편리하게 사용할 수 있는 자바스크립트 인라인 기능을 제공한다.
자바스크립트 인라인 기능은 다음과 같이 사용 한다.
<script th:inline="javascript">
BasicController
1
2
3
4
5
6
7
@GetMapping("/javascript")
public String javascript(Model model) {
model.addAttribute("user", new User("userA", 10));
addUser(model);
return "basic/javascript";
}
/resources/templates/basic/javascript.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 자바스크립트 인라인 사용 전 -->
<script>
var username = [[${user.username}]];
var age = [[${user.age}]];
//자바스크립트 내추럴 템플릿
var username2 = /*[[${user.username}]]*/ "test username";
//객체
var user = [[${user}]];
</script>
<!-- 자바스크립트 인라인 사용 후 -->
<script th:inline="javascript">
var username = [[${user.username}]];
var age = [[${user.age}]];
//자바스크립트 내추럴 템플릿
var username2 = /*[[${user.username}]]*/ "test username";
//객체
var user = [[${user}]];
</script>
<!-- 자바스크립트 인라인 each --><script th:inline="javascript">
[# th:each="user, stat : ${users}"]
var user[[${stat.count}]] = [[${user}]];
[/]
</script>
</body>
</html>

자 사용 전 항목 var username = [[${user.username}]]; 가 렌더링 된 걸 보자.

"userA" 가 되어야 하는데, 그냥 userA라 나온다.
제대로 하려면 var username = "[[${user.username}]]"; 이런 식으로 해줘야 할 것이다.
다른 부분도 문제가 많다.
텍스트 렌더링
var username = [[${user.username}]];- 인라인 사용 전 →
var username = userA; - 인라인 사용 후 →
var username = "userA";
- 인라인 사용 전 →
인라인 사용 전 렌더링 결과를 보면 userA가 변수 이름 그대로 남아있다. 타임리프 입장에서는 정확하게 렌더링 한 것이지만
아마 개발자가 기대한 것은 "userA"일 것이다.
결과적으로 userA가 변수 명으로 사용되어서 자바스크립트 오류가 발생한다.
인라인 사용 후 렌더링 결괄르 보면 문자 타입인 경우 "를 추가해 준다.
추가로 자바스크립트 에서 문제가 될 수 있는 문자가 포함되어 있으면 이스케이프 처리도 해준다. 예) "→ \"
자바스크립트 내추럴 템플릿
타임리프는 HTML 파일을 직접 열어도 동작하는 내추럴 템플릿 기능을 제공한다.
자바스크립트 인라인 기능을 사용하면 주석을 활용해서 이 기능을 사용할 수 있다.
var username2 = /*[[${user.username}]]*/ "test username";- 인라인 사용 전 →
var username2 = /*userA*/ "test username"; - 인라인 사용 후 →
var username2 = "userA";
- 인라인 사용 전 →
인라인 사용 전 결과를 보면 정말 순수하게 그대로 해석 했다.
따라서 내추럴 템플릿 기능이 동작하지 않고, 심지어 렌더링 내용이 주석 처리 되어 버린다.
인라인 사용 후 결과를 보면 주석 부분이 제거되고, 기대한 "userA"가 정확하게 적용된다.
객체
타임리프의 자바스크립트 인라인 기능을 사용하면 객체를 JSON으로 자동으로 변환해준다.
var user = [[${user}]];- 인라인 사용 전 →
var user = BasicController.User(username=userA, age=10); - 인라인 사용 후 →
var user = {"username":"userA","age":10};
- 인라인 사용 전 →
인라인 사용 전에는 객체를 toString()으로 호출해 버린다.
인라인 사용 후에는 객체를 JSON으로 변환해 준다.
자바스크립트 인라인 each
자바스크립트 인라인은 each를 지원하는데, 다음과 같이 사용한다.
1
2
3
4
5
6
7
<script th:inline="javascript">
[# th:each="user, stat : ${users}"]
var user[[${stat.count}]] = [[${user}]];
[/]
</script>
결과
1
2
3
4
5
6
7
<script>
var user1 = {"username":"userA","age":10};
var user2 = {"username":"userB","age":20};
var user3 = {"username":"userC","age":30};
</script>
댓글남기기