머스테치(Mustache)란 무엇인가 ?

2

Spring

목록 보기
7/12
post-custom-banner

자바 진영에서 흔히 이야기 하는 서버 템플릿 엔진은 JSP, Velocity, Freemarker, Thymeleaf, Mustache 등등 여러가지 템플릿 엔진이 존재한다.

위에서 말한 템플릿 엔진의 단점들은 다음과 같다.

  • JPS, Velocity : 스프링 부트에서는 권장하지 않는 템플릿 엔진임
  • Freemarker : 템플릿 엔진으로는 너무 과하게 많은 기능을 지원한다 -> 숙련도가 낮을수록 비즈니스 로직이 추가될 가능성이 높다
  • Thymleaf : 스프링 진영에서 적극적으로 지원하는 템플릿 엔진이지만 문법이 어렵다.

반면 머스테치의 장점이다.

  • 문법이 다른 템플릿 엔진보다 쉽다.
  • 비즈니스 로직을 사용할 수 없다. -> View의 역할과 서버의 역할이 명확하게 구분된다.
  • 콧수염이 상당히 마음에 든다.

템플릿 엔진은 화면(View) 역할에만 충실하는 것이 좋다. 너무 많은 기능을 제공하면 API와 템플릿 엔진, 자바스크립트가 서로 로직을 나눠 갖게 되어서 유지보수가 매우 어려워진다.


머스테치 플러그인 설치

맥의 경우 Preferences, 윈도우의 경우 Setting -> Plugins Mustache 검색 후 install -> restart


머스테치 사용

프로젝트에서 머스테치를 편하게 사용할 수 있도록 build.gradle에 의존성을 추가해주자

dependencies{
	compileOnly 'org.springframework.boot:spring-boot-starter-mustache'
}

의존성을 추가한 것과 같이 머스테치는 스프링 부트에서 공식적으로 지원하는 템플릿 엔진이다.

의존성만 추가하면 다른 스타터 패키지와 마찬가지로 추가 설정 없이 설치가 끝난다.

머스테치의 파일 위치는 기본적으로 main/resources/templates 이다.

머스테치를 사용해서 간단한 게시판 화면을 만들어보자.


index.mustache

게시판의 첫 페이지이다.

<html>
<head>
    <title>
        템플릿 엔진으로 게시판 만들기
    </title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>머스테치로 구현하는 게시판</h1>
</body>
</html>

이 화면을 첫 화면으로 나타나게 하기 위해서 컨트롤러를 작성해준다.

IndexController

@Controller
public class IndexController {

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

너무 간단해 보이니 글 등록 버튼을 추가해보자

Index.mustache

<html>
<head>
    <title>
        템플릿 엔진으로 게시판 만들기
    </title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
{{>layout/header}}

<h1>머스테치로 구현하는 게시판</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>
        </div>
    </div>
</div>

{{>layout/footer}}
</body>
</html>

글 등록 버튼을 누르면 /posts/save 경로로 요청이 들어오기 때문에 컨트롤러를 만들어 주어야한다.


IndexController

public class IndexController{

(기존 코드)

    @GetMapping("/posts/save")
    public String postsSave(){
        return "posts-save";
    }
}

header.mustache

<!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>

footer.mustache

<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>
</body>
</html>

header와 footer은 부트스트랩의 라이브러리를 가져온 모습이다. html이랑 다른점은 header와 footer를 사용하는 부분인데

{{>layout/header}}

이렇게 {{> }} 안에 위치만 잘 써준다면 매우 쉽게 mustache 파일을 불러올 수 있다.

결과 화면


글 등록 버튼을 만들었으니 게시글 등록 화면을 만들어보자

posts_save

{{>layout/header}}

<h1>게시글 등록</h1>

<div class="col-md-12">
    <div class="col-md-4">
        <form>
            <div class="form-group">
                <label for="title">제목</label>
                <input type="text" class="form-control" id="title" placeholder="제목을 입력하세요">
            </div>
            <div class="form-group">
                <label for="author"> 작성자 </label>
                <input type="text" class="form-control" id="author" placeholder="작성자를 입력하세요">
            </div>
            <div class="form-group">
                <label for="content"> 내용 </label>
                <textarea class="form-control" id="content" placeholder="내용을 입력하세요"></textarea>
            </div>
        </form>
        <a href="/" role="button" class="btn btn-secondary">취소</a>
        <button type="button" class="btn btn-primary" id="btn-save">등록</button>
    </div>
</div>

{{>layout/footer}}

결과 화면

하지만 아직 게시글 등록 화면에 등록 버튼 기능이 없다. API를 호출하는 JS가 없기 때문이다.

이 위치에 index.js 파일을 만들어주자

index.js


var main = {
    init: function () {
        var _this = this;
        $('#btn-save').on('click', function () {
            _this.save();
        });

        $('#btn-update').on('click', function () {
            _this.update();
        });

        $('#btn-delete').on('click', function () {
            _this.delete();
        });
    },
    save: function () {
        var data = {
            title: $('#title').val(),
            author: $('#author').val(),
            content: $('#content').val()
        };

        $.ajax({
            type: 'POST',
            url: '/api/v1/posts/create',
            dataType: 'json',
            contentType: 'application/json; charset=utf-8',
            data: JSON.stringify(data)
        }).done(function () {
            alert('글이 등록되었습니다.');
            window.location.href = '/';
        }).fail(function (error) {
            alert(JSON.stringify(error));
        });
    }
}

main.init();
  • API

머스테치가 이를 사용하기 위해서는 footer에 추가해주어야한다.

<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>

<!--index.js 추가-->
<script src="/js/app/index.js"></script>
</body>
</html>

결과 화면

DB

값이 잘 들어간 것을 확인할 수 있다. local_date_time이 null인 이유는 엔티티가 아니어서 들어가지 않았다. 대신 create_date 컬럼이 생겼다.


reference

post-custom-banner

0개의 댓글