본문 바로가기
SpringBoot

스프링부트 viewresolver와 Mustache

by 김마리님 2020. 7. 13.

이전에, responsebody를 붙이지 않으면 파일 명을 찾아간다고 했었다.

 

-IndexController.java

	@GetMapping({"","/"})
	public @ResponseBody String index() {
		return "index";
	}

 

여기서 responsebody 어노테이션을 빼면 어떻게 될까?

다음과 같이 404 에러가 발생한다. 왜냐면, 경로에 파일이 없기 때문이다. 

여기서 어노테이션을 제거하면 파일은 다음과 같은 폴더의 경로를 찾아간다.

 

 

이 때, 스프링은 파일의 템플릿 엔진을 제공하는데, 이 파일의 템플릿 엔진은 스프링부트 프로젝트를 처음 만들 때 지정할 수 있다.

필자는 여기서 Mustache를 사용한다.

이 파일들은 각자의 확장자를 가지는데, 현재 사용하는 mustache 같은 경우는 index.mustache처럼 .mustache 확장자를 가진다.

 

그럼, 저 tamplate의 실제 경로는 어떻게 될까?

실제 경로는 다음과 같다.

/viewresolver/src/main/resources/templates(prefix)/index.mustache(suffix)

여기서 붉은 색의 경로는 어떤 템플릿 엔진을 사용하던 같은 값을 가진다. 이를 prefix(프리픽스) 라고 하고, 보라색은 확장자에 따라 변하는데, 이를 서픽스(suffix)라고 한다.

 

하지만, 스프링 부트에는 Mustache 파일을 만들어주지 않기 때문에 ^^ ....

 

꼼수처럼(?) 파일을 만드는 법이 있다.

먼저, html 파일을 생성한다.

 

이후 F2로 rename을 하면서 확장자를 .mustache로 변경하면 끝.

 

이제 파일을 가져와보자.

	@GetMapping({"","/"})
	public String index(){
		//viewresolver/src/main/resources/templates(prefix)/index.mustache(surfix)
		return "index";
	}
}

다음과 같이 손쉽게 경로 설정의 필요없이 파일을 불러올 수 있다.

 

Mustache 문법은 간단하다. jsp처럼 변수를 가져올 때는 다음과 같은 방법을 쓰면 되기 때문이다.

{{(변수 이름)}}

 

또, 우리가 자바에서 변수값을 받아올때는 requestDispatcher을 사용해서 response를 전달하는데, 이를 springboot는 따로 내장함수로 지원한다. Model이라는 값을 이용하여 지원한다.

이제, attribute 함수를 통해 값을 이동시켜보자.

 

-IndexController.java

package com.mary.viewresolver;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller //IoC
public class IndexController {
	
	@GetMapping({"","/"})
	public String index(Model model) { //==requestDispather
		String name="cos";
		String password="1234";
		int num=10;
		model.addAttribute("name" , name);
		model.addAttribute("password" , password);
		model.addAttribute("num" , num);
		//viewresolver/src/main/resources/templates(prefix)/index.mustache(surfix)
		return "index";
	}
}

 

-index.mustache

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>index.mustache파일입니다.</h1>
<h2>name : {{name}}</h2>
<h2>password : {{password}}</h2>
<h2>num : {{num}}</h2>

</body>
</html>

 

Mustache로 데이터 모델을 만들어서 출력하는 것도 가능하다.

일반적인 jsp를 하듯 데이터 모델을 만들자.

 

-Member.java

package com.mary.viewresolver;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Member {
	private int id;
	private String username;
	private String phone;
}

 

그리고, 일반적으로 빌드를 해보자.

 

-IndexController.java

		@GetMapping("/model/data")
		public String modelData(Model model) { //DI
			Member member=Member.builder()
														.id(1)
														.username("ssar")
														.phone("00011112222")
														.build();
			model.addAttribute("member",member);
			return "modelData";
		}

 

-modelData.mustache

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>modelData 페이지</h1>
<h2>{{member.id}}</h2>

</body>
</html>

 

 

Mustache 문법도 다른 문법과 마찬가지로 반복문과 조건문이 가능하다

변수 값에 #를 추가하면 되는데, #가 붙은 변수가 true(존재한다면) 내부 조건을 수행하고, 아니라면 수행하지 않는다.

 

- modelData.mustache

<h1>#문법 : 조건문 혹은 반복문 처리</h1>
{{#member}}
	<h2>{{id}}</h2>
	<h2>{{username}}</h2>
	<h2>{{phone}}</h2>
{{/member}}

 

 

받아오는 변수가 컬렉션처럼 반복할 수 있는 변수이면 mustache 가 인식하고 자동으로 반복문 처리를 한다.

 

-IndexController.java

	@GetMapping("/model/array")
	public String modelArray(Model model) { //DI
		Member member1=Member.builder()
				.id(1)
				.username("ssar")
				.phone("00011112222")
				.build();
		Member member2=Member.builder()
													.id(2)
													.username("cos")
													.phone("00033332222")
													.build();
		List<Member>members=new ArrayList<>();
		members.add(member1);
		members.add(member2);
		model.addAttribute("members",members);
		model.addAttribute("user",true);
		return "modelArray";
	}

 

-modelArray.mustache

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
{{members}}
<hr/>
{{members.0}}
<hr/>
{{#members}}
	<h2>{{id}}</h2>
	<h2>{{username}}</h2>
	<h2>{{phone}}</h2>
	<hr/>
{{/members}}
<hr/>

</body>
</html>

 

또, true를 false로, false를 true로 boolean 타입을 반전해주는 것이 ^ 이다.

 

-modelArray.mustache

<hr/>
{{#user}}
	<h2>유저가 있습니다.</h2>
{{/user}}
<hr/>
{{^user}}
	<h2>유저가 없습니다.</h2>
{{/user}}
</body>
</html>

 

마지막으로, 파일을 합하는 기호는 {{>}} 이다.

-header.mustache

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>부분 템플릿</title>
</head>
<body>
<h1>Header부분</h1>
<hr/>

 

-footer.mustache

<hr/>
<h1>Footer부분</h1>
</body>
</html>

 

- IndexController.java

	@GetMapping("/layout")
	public String layout() {
		return "layout";
	}

 

-layout.mustache

{{>layout/header}}
<h1>레이아웃 파일입니다.</h1>
{{>layout/footer}}

반응형