Mustache
✒️ 2025-05-16 09:36 내용 수정
스프링부트3 자바 백엔드 개발입문 내용 참고 및 정리
Web template system
- 공식 문서 : https://mustache.github.io/
- 참고 자료 : wikipedia Mustache(template system)
- 모바일과 웹 어플리케이션에 사용되는 템플릿 시스템이다.
- if나 else와 같은 조건문이나 for 루프와 같은 제어 흐름 선언이 없기에 논리가 없는 시스템으로 불린다.
- 하지만 루프와 조건 평가는 섹션 태그 처리 목록과 익명 함수를 사용하여 수행할 수 있다.
- 다양한 언어를 지원하고, 사용법이 간단하다.
Spring boot에서 사용 설정
- IDE는 IntelliJ Community edition을 사용했다.
- Spring boot 프로젝트에서
src/main/resources/templates폴더에test.mustache파일을 생성한다.
- 상단에 mustache 파일을 지원하는 플러그인이 발견되었다는 알림이 뜨면
Install Handlebars/Mustache plugin을 클릭해 플러그인을 다운 받는다.
mustache파일에서!를 입력하고Tab키를 누르면 자동으로 html 코드가 작성된다.
doc을 입력하고Tab키를 눌러도 html 코드가 작성되지만lang설정 등 일부가 빠져있다.
- mustache 파일을 전송할 Controller를 작성한다. 먼저
src/main/java/package_name에controller라는 패키지를 만든다. - 패키지 내에
FirstController.java파일을 만든다.
- Controller임을 명시하는
@ControllerAnnotation을 추가해주고, URL 요청을 받을@GetMapping을 추가해newToMustache()메소드가 URL 요청이 들어왔을 때 동작을 수행할 수 있도록 설정한다. test.mustache를 반환하기 위해 파일명만 작성해return "test";를 작성한다.
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class FirstController {
@GetMapping("/test")
public String newToMustache(Model model) {
return "test"; // test.mustache 파일을 반환
}
}
src/main/java/package_name/ProjectNameApplication.java파일을 우클릭해서Run Application을 선택해 서버를 가동하고,http://localhost:port/test를 입력해 view가 잘 출력되는지 확인한다.
- 이제
test.mustache파일을 뷰 템플릿 시스템으로 사용해보기 위해 파일 내에{{변수명}}을 추가한다.
<h1>Hello Mustache!</h1>
<p>{{username}}님 반갑습니다!</p>
FirstController.java파일에서org.springframework.ui.Model를 import 한다.Model model을newToMustache()매소드의 인자로 추가하고,model.addAttribute("변수명", "값")을 추가해 템플릿 엔진에서 지정한 변수명에 값을 넣어주도록 설정한다.
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class FirstController {
@GetMapping("/test")
public String newToMustache(Model model) {
model.addAttribute("username", "tester"); // username 변수명에 tester를 추가
return "test"; // test.mustache 파일을 반환
}
}
- 서버를 다시 실행해서 같은 url을 요청했을 때 username 부분이
Model로 넣어준 값인지 확인한다.- 한글이 깨져서 나온다면
application.properties파일이나application.yml파일에서 아래 설정을 추가한다.
- 한글이 깨져서 나온다면
# .properties 파일
server.servlet.encoding.force=true
# .yml 파일
server:
servlet:
encoding:
force: true
문법
1. 변수 설정
{{변수명}}로 설정한다.
<!-- { "name" : "tester" } -->
<p>Hello, {{name}}!</p>
2. HTML 이스케이프 방지
- mustache는 변수 값에 들어오는 HTML를 이스케이프하기에 이를 원치 않는다면
{{{변수명}}}으로 설정한다.
<!-- { "name" : "<strong>Jake</strong>" } -->
<p>Hello, {{name}}!</p>
<!-- { "name" : "<strong>Jake</strong>" } -->
<p>Hello, {{{name}}}!</p>
3. 주석
{{! }}으로 표기한다.
<!-- 이 부분은 html 주석 -->
{{! 이 부분은 mustache 주석 }}
<p>Hello, {{{name}}}!</p>
4. 조건부 렌더링(sections)
{{#section}}...{{/section}}으로 특정 조건에서만 템플릿을 렌더링할 수 있다.
<p>Hello, {{{name}}}!</p>
{{#isActive}}
{{{name}}} is Active!
{{/isActive}}
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class FirstController {
@GetMapping("/test")
public String newToMustache(Model model) {
model.addAttribute("name", "Jake");
return "test";
}
}
- 이번엔
model.addAttribute("isActive", true);를 추가해서 비교해본다.
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class FirstController {
@GetMapping("/test")
public String newToMustache(Model model) {
model.addAttribute("name", "Jake");
model.addAttribute("isActive", true);
return "test";
}
}
5. 배열 반복
- 조건부 렌더링처럼
{{#section}}...{{/section}}로 작성하고, 배열 요소는{{.}}로 출력한다.- mustache에서 문법에 사용된 변수가 데이터 묶음인 경우엔 내부 코드가 반복되어 실행된다.
- JPA로 DB Read 수행하기#데이터 리스트 조회하기 코드 참고.
<p>Hello, {{name}}!</p>
<ul>
{{#items}}
<li>{{.}}</li>
{{/items}}
</ul>
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class FirstController {
@GetMapping("/test")
public String newToMustache(Model model) {
String[] fruits = {"apple", "banana", "watermelon"};
model.addAttribute("name", "Jake");
model.addAttribute("items", fruits);
return "test";
}
}
6. 역조건 렌더링(inverted sections)
{{^section}}...{{/section}}으로 작성하며, 데이터가 비어있거나false일때만 렌더링된다.
<!-- name에만 값을 넣고, isLoggedin에는 값을 넣지 않았다 -->
<p>Hello, {{name}}!</p>
{{^isLoggedin}}
Please log in!
{{/isLoggedin}}
- 이번엔
isLoggedin에 아무 값을 추가했다.
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class FirstController {
@GetMapping("/test")
public String newToMustache(Model model) {
model.addAttribute("name", "Jake");
model.addAttribute("isLoggedin", "yes");
return "test"; // test.mustache 파일을 반환
}
}
7. 다른 mustache 파일의 내용 가져오기(include)
src/main/resources/templates폴더에header.mustache와footer.mustache파일을 만들고,test.mustache파일에 두 파일의 내용을 가져온다.
{{! header.mustache }}
<p>Welcome!</p>
{{! footer.mustache }}
<p>Footer!</p>
{{! test.mustache }}
{{> header}}
<p>Hello, {{name}}!</p>
{{> footer}}
- 만약 불러올 파일의 위치가
src/main/resources/templates내의 다른 경로라면,{{>}}를 작성할 파일의 위치를 기준으로 상대 경로로 작성한다.
{{! index.mustache }}
{{> layouts/header}}
<p>Hello, {{name}}!</p>
{{> layouts/footer}}
8. 객체의 속성 접근
{{Object.property}}로 작성하면Object내의property에 접근할 수 있다.
<p>Hello, {{name}}!</p>
<div>
<p>car name : {{car.name}}</p>
<p>number : {{car.number}}</p>
</div>
- 테스트를 위해
Car라는 클래스를 만들고,name과number를 추가한다.
package com.example.demo.DTO;
import lombok.Data;
@Data // lombok
public class Car {
String name;
Integer number;
}
package com.example.demo.controller;
import com.example.demo.DTO.Car;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class FirstController {
@GetMapping("/test")
public String newToMustache(Model model) {
Car newCar = new Car();
newCar.setName("BMW");
newCar.setNumber(1234);
model.addAttribute("name", "Jake");
model.addAttribute("car", newCar);
return "test"; // test.mustache 파일을 반환
}
}