참고
Spring Boot & Thymeleaf 시리즈는 김영한 님의 "스프링 MVC 2편 - 백엔드 웹 개발 활용 기술" 강의를 정리한 글입니다. 글에 첨부된 사진은 해당 강의의 강의 자료에서 캡쳐한 것입니다. 제 Github에만 올려뒀다가, 정보 공유와 강의 홍보(?)를 위해 블로그에도 업로드합니다.
스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - 인프런 | 강의
웹 애플리케이션 개발에 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. MVC 2편에서는 MVC 1편의 핵심 원리와 구조 위에 실무 웹 개발에 필요한 모든 활용 기술들을 학습할 수 있
www.inflearn.com
마크다운 형식으로 작성한 글을 블로그에 다시 올리는 거라 가독성이 많이 떨어집니다. 조금더 편하게 보시려면 아래의 Github repository에서 보시면 됩니다.
GitHub - Kloong1/TIL: Today I Learned.
Today I Learned. Contribute to Kloong1/TIL development by creating an account on GitHub.
github.com
타임리프 - 자바스크립트 인라인
- 타임리프는 자바스크립트 코드 안에서 타임리프를 편리하게 사용할 수 있는 자바스크립트 인라인 기능을 제공한다.
- 자바스크립트 인라인 기능은 다음과 같이 적용하면 된다.
<script th:inline="javascript">
BasicController.java 내용 추가
package kloong.thymeleaf.basic;
import ... //생략
@Controller
@RequestMapping("/basic")
public class BasicController {
@GetMapping("/javascript")
public String javascript(Model model) {
model.addAttribute("user", new User("userA", 10));
addUsers(model);
return "basic/javascript";
}
private void addUsers(Model model) {
List<User> list = new ArrayList<>();
list.add(new User("userA", 10));
list.add(new User("userB", 20));
list.add(new User("userC", 30));
model.addAttribute("users", list);
}
@Data
static class User {
private String username;
private int age;
public User(String username, int age) {
this.username = username;
this.age = age;
}
}
}
/resources/templates/basic/javascript.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 자바스크립트 인라인 사용 전 -->
<script>
var username = [[${user.username}]]; //userA -> 문자열 아니므로 자바스크립트 오류
var age = [[${user.age}]]; //10
//자바스크립트 내추럴 템플릿
var username2 = /*[[${user.username}]]*/ "test username";
//객체
var user = [[${user}]]; //toString() 호출 결과 -> 자바스크립트 오류
</script>
<!-- 자바스크립트 인라인 사용 후 -->
<script th:inline="javascript">
var username = [[${user.username}]];
var age = [[${user.age}]];
//자바스크립트 내추럴 템플릿
var username2 = /*[[${user.username}]]*/ "test username";
//객체
var user = [[${user}]];
</script>
</body>
</html>
실행 결과 - 자바스크립트 인라인 사용 전
<!-- 자바스크립트 인라인 사용 전 -->
<script>
var username = userA;
var age = 10;
//자바스크립트 내추럴 템플릿
var username2 = /*userA*/ "test username";
//객체
var user = BasicController.User(username=userA, age=10);
</script>
- 자바스크립트 인라인을 사용하지 않으면, 타임리프는 자신이 렌더링하고 있는 부분이 자바스크립트 코드 내부임을 알 수가 없다.
- 따라서 평소 하던 그대로 렌더링을 한다.
[[${user.username}]]
을userA
로 렌더링 한다.[[${user.age}]]
을10
으로 렌더링 한다./*[[${user.username}]]*/
을/*userA*/
로 렌더링 한다. 자바스크립트 인라인을 사용하지 않고 있기 때문에 타임리프는 자바스크립트의 주석인/* */
를 무시하고 그대로 렌더링한다.[[${user}]]
는user.toString()
의 값으로 렌더링한다.
- 타임리프는 server side에서 렌더링을 하던대로 잘 했다.
- 문제는 server side에서 타임리프에 의해 렌더링 된 HTML을 받은 웹 브라우저가 자바스크립트 코드를 실행시킬 때 발생한다.
실행 결과 - 자바스크립트 인라인 사용 후
<!-- 자바스크립트 인라인 사용 후 -->
<script>
var username = "userA";
var age = 10;
//자바스크립트 내추럴 템플릿
var username2 = "userA";
//객체
var user = {"username":"userA","age":10};
</script>
자바스크립트 인라인의 동작
자바스크립트 인라인을 사용하면, 타임리프는 해당 부분이 자바스크립트 코드 내부임을 알게 된다. 그래서 자바스크립트 코드에 맞춰서 렌더링 방식을 다르게 하여 동작한다.
텍스트 렌더링
var username = [[${user.username}]];
- 인라인 사용 전:
var username = userA
- 인라인 사용 후:
var username = "userA"
- 인라인 사용 전:
- 인라인 사용 전 결과를 보면
[[${user.username}]]
가userA
로 렌더링 된다. - 개발자가 원하는 것은
var username
에userA
라는 값을 가진 문자열을 대입하는 작업일 것이다. - 하지만 타임리프는 잘못이 없다. 코드 그대로 정확하게 렌더링 했다. 문제는 자바스크립트가
userA
를 문자열로 인식할 수가 없다. 큰따옴표로 감싸져 있지 않기 때문에 당연하다. var username = "[[${user.username}]]"
이렇게 하는 것도 방법이 될 수는 있다. 하지만 개발자가 모든 변수에 대해서 변수의 타입이 문자열이면 큰따옴표를 붙이고, 아니면 빼는 작업을 하는 건 너무 귀찮고 오류가 날 가능성도 높다.- 자바스크립트 인라인을 사용하면 타임리프가 변수 타입이 문자열인 경우 렌더링 결과를 큰따옴표로 감싸준다.
- 추가로 자바스크립트에서 문제가 될 수 있는 문자가 포함되어있으면 escape 처리도 해준다.
- ex.
"
->\"
- ex.
자바스크립트 natural template
- 타임리프는 HTML 파일을 직접 열어도 동작하는 내추럴 템플릿 기능을 제공한다.
- 자바스크립트 인라인을 사용하면, 자바스크립트 주석을 활용해서 자바스크립트 코드 내부에서도 natural template 기능을 사용할 수 있다.
var username2 = /*[[${user.username}]]*/ "test username";
- 인라인 사용 전:
var username2 = /*userA*/ "test username";
- 인라인 사용 후:
var username2 = "userA";
- 인라인 사용 전:
- 개발자는 HTML 파일을 직접 여는 상황 같이 타임리프가 렌더링을 하지 않는 경우에는
username2
에"test username"
이 대입 되고, 타임리프가 렌더링을 하면"userA"
가 대입되는 결과를 원한다. 즉 natural template 기능을 원하는 것이다. - 실제로
/* */
는 자바스크립트의 주석이기 때문에, 파일을 직접 열면 웹 브라우저는/*[[${user.username}]]*/
를 무시하고username2
에"test username"
을 대입하게 된다. - 문제는 자바스크립트 인라인을 사용하지 않으면, 타임리프로 렌더링을 하는 경우에도 타임리프가 자바스크립트 주석을 이해하지 못하기 때문에, 평소 하던대로 다음과 같이 렌더링한다.
var username2 = /*userA*/ "test username";
- 이러면 타임리프가 동작해도 웹 브라우저는
/* */
내부의 값을 무시하기 때문에username2
에는 여전히"test username"
이 대입되게 된다.
- 하지만 자바스크립트 인라인을 사용하면 타임리프가 렌더링을 했을 때
/* */
가 제거되고,"userA"
가username2
에 대입되게 된다. - 즉 자바스크립트 인라인을 통해 자바스크립트 코드 내부에서도 natural template 기능을 사용할 수 있게 된다.
객체 대입
- 타임리프의 자바스크립트 인라인 기능을 사용하면 객체를 JSON으로 자동으로 변환해준다.
var user = [[${user}]];
- 인라인 사용 전:
var user = BasicController.User(username=userA, age=10);
- 인라인 사용 후:
var user = {"username":"userA","age":10};
- 인라인 사용 전:
- 인라인 사용 전에는 타임리프가 객체의
toString()
을 호출한다. - 인라인 사용 후에는 타임리프가 객체를 JSON 형태로 변환해준다.
- 자바스크립트에서는 JSON을 변수에 대입할 수 있다.
자바스크립트 인라인 th:each
자바스크립트 인라인은 자바스크립트 코드 내에서도 th:each
를 사용할 수 있게 해준다.
resources/templates/basic/javascript.html 에 추가
<!-- 자바스크립트 인라인 each -->
<script th:inline="javascript">
[# th:each="user : ${users}"]
var user[[${userStat.count}]] = [[${user}]];
[/]
</script>
자바스크립트 인라인 each 결과
<script>
var user1 = {"username":"userA","age":10};
var user2 = {"username":"userB","age":20};
var user3 = {"username":"userC","age":30};
</script>
'Spring > Spring Boot & Thymeleaf' 카테고리의 다른 글
[Spring Boot & Thymeleaf] 16. 템플릿 레이아웃 (0) | 2022.10.24 |
---|---|
[Spring Boot & Thymeleaf] 15. 템플릿 조각 (0) | 2022.10.24 |
[Spring Boot & Thymeleaf] 13. Block 태그 (0) | 2022.10.24 |
[Spring Boot & Thymeleaf] 12. 주석 (0) | 2022.10.24 |
[Spring Boot & Thymeleaf] 11. if, unless, switch (0) | 2022.10.24 |
댓글