[springboot-webserivce] 머스테치로 기본 페이지, 글 등록 페이지 제작
Updated:
[2020.12.28] 부터 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 책을 통해 스프링 공부를 시작했다.
공부한 내용을 글로 정리하려고 한다.
그래야 나중에 다시 찾아보며 공부 할 수 있을테니까 !!
🥸 Mustache
머스테치는 수많은 언어를 지원하는 템플릿 엔진이다.
자바와 자바스크립트를 모두 지원하기 때문에 하나의 문법으로 서버, 클라이언트 템플릿 사용이 가능하다.
또 문법이 다른 템플릿 엔진에 비해 간단하고 로직 코드를 사용할 수 없어 View 와 서버의 역할이 명확하게 분리된다.
인텔리제이에서 머스테치 플러그인을 사용하면 문법 체크, HTML 문법 지원, 자동 완성 등의 기능이 제공된다.
때문에 머스테치와 앞서 만들었던 API 를 이용해 페이지를 만들어 보려고 한다.
🥮 Mustache 라이브러리 등록
머스테치는 스프링 부트에서 공식적으로 지원하는 템플릿 엔진이다.
따라서 build.gradle 에 라이브러리를 추가만 시켜주면 된다.
...
dependencies {
...
compile('org.springframework.boot:spring-boot-starter-mustache')
testCompile('org.springframework.boot:spring-boot-starter-test')
}
그리고 머스테치 플러그인을 다운받아 적용하면 준비는 모두 끝났다.
🍜 index.mustache 생성
머스테치의 파일 위치는 기본적으로 src/main/resources/templates 이다.
이 위치에 머스테치 파일을 두면 스프링 부트가 알아서 로딩한다.
index 파일을 만들기 전에 앞으로 프론트는 부트스트랩을 이용해 만들 것이다.
그렇게 되면 모든 머스테치 파일에 부트스트랩을 추가해야 하기 때문에 레이아웃 방식을 사용할 것이다.
resources/templates/layout 폴더에 header.mustache, footer.mustache 파일을 만들자.
resources/templates/layout/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>
resources/templates/layout/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 를 보게 되면 css 는 header 에 js 는 footer 에 위치시켰다.
이유는 사용자 경험을 위해서인데 html 은 코드 위에서부터 차례로 수행이 되기 때문에
head 부분 로딩을 끝마친 뒤 body 부분 로딩이 시작된다.
그런데 만약 js 용량이 커 로딩이 느려지면 사용자는 빈 화면을 보고 있어야 한다.
그렇다고 css 도 밑으로 내려버리면 사용자는 깨진 화면을 보고 있어야 하기 때문에 css 는 위, js 는 아래로 내린다.
이제 index 페이지를 만들고 글 등록 버튼을 넣으려고 한다.
모든 머스테치 파일을 생성 할 때 맨 위는 {{>layout/header}}, 맨 밑은 {{>layout/footer}} 코드를 넣어주면 된다.
앞으로 다른 머스테치 파일 코드를 올리는 경우 레이아웃 적용 코드는 생략하려고 한다.
이유는 코드펜스를 통해 코드를 올려도 마크다운에서 레이아웃 적용 코드는 실행이 되어버려 오류가 발생한다..
resources/templates/index.mustache
<h1>BOKS - 스프링 부트와 AWS로 혼자 구현하는 웹 서비스</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>
index 페이지를 만들었으니 URL 에 머스테치 파일을 매핑하려고 한다.
이 주소에 해당하는 컨트롤러를 만들기 위해 java/com/boks/springboot/web/IndexController 를 생성한다.
package com.boks.springboot.web;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class IndexController {
@GetMapping("/")
public String index() {
return "index";
}
}
그리고 어플리케이션을 실행 시킨뒤 localhost:8080 으로 접속하게 되면 오류 없이 잘 실행되는 모습을 볼 수 있다.
🔨 글 등록 버튼 기능 추가
index 파일의 a 태그를 보게 되면 글 등록을 누르는 경우 /posts/save 주소로 이동하게 된다.
하지만 URL 과 매핑된 머스테치 파일이 없기 때문에 아무일도 일어나지 않는다.
resources/templates/posts-save.mustache
<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>
이렇게 /posts/save 주소와 매핑 될 글 작성 양식 머스테치 파일을 만든 뒤 IndexController 에서 매핑을 해준다.
java/com/boks/springboot/web/IndexController
...
@Controller
public class IndexController {
...
@GetMapping("/posts/save")
public String postsSave() {
return "posts-save";
}
}
URL 과 머스테치 파일을 매핑 한 뒤 localhost:8080 에 접속 해 글 등록 버튼을 누르게 되면
글 양식이 나타나게 된다.
🧲 등록 버튼과 API 연결
여기까지 완료 한 뒤 등록 버튼을 누르면 아무일도 일어나지 않는다.
등록 버튼을 눌렀을 때 API 를 호출해주는 JS 가 없기 때문이다.
resources/static/js/app/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',
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();
이 코드를 보면 var main = { } 로 함수들을 묶어 놓은 것을 볼 수 있다.
그렇게 한 이유는 다른 JS 파일이 같은 이름의 함수를 가지고 있는 경우 나중에 로딩 된 함수로 덮어 씌워진다.
때문에 var index 객체를 만들어 해당 객체에서 필요한 모든 함수를 선언한다.
이렇게 하면 객체 안에서만 함수가 유효하기 때문에 겹칠 위험이 사라진다고 한다.
버튼과 API 를 연결해 준 뒤 index.mustache 파일이 사용할 수 있도록 footer 에 추가해 준다.
resources/templates/layout/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>
<!--index.js 추가-->
<script src="/js/app/index.js"></script>
</body>
</html>
🌯 등록 기능 테스트
등록 기능을 모두 구현하였기 때문에 직접 브라우저를 통해 테스트 해보려고 한다.
어플리케이션을 실행하고 글을 작성해보자.
등록을 누르고 데이터베이스를 확인하기 위해 localhost:8080/h2-console 로 접속해 쿼리문을 날려보자.
글 저장이 잘 된 것을 알 수 있다.
📕 정리
우선 자바스크립트 문법은 아예 모르는 상태로 진행했기 때문에 자바스크립트 코드는 예제 그대로 복사했다.
다음은 전체 글 조회하기 기능을 만들어야 하는데 진행 하기전에 이 과정을 한 번 이해하고 넘어가야겠다.
그러기 위해서 부트스트랩과 자바스크립트를 공부 할 필요가 있다.
Leave a comment