[Spring] 4장 Mustache로 화면 구성하기

Date:

카테고리:

4장 - Mustache를 통해 화면 구성하기

4.1 서버 템플릿 엔진과 머스테치 소개

4.1.1 템플릿 엔진이란?

  • 지정된 템플릿 양식과 데이터가 합쳐져 HTML 문서를 출력하는 소프트웨어


서버 템플릿 엔진(ex-Spring + JSP, Thymeleaf)

  • JSP는 서버에서 구동하며 서버에서 Java 코드로 문자열을 만든 뒤 이 문자열을 HTML로 변환하여 브라우저로 전달!
  • MVC로 쪼개서 뷰를 템플릿 엔진을 통해 랜더링된 HTML을 클라이언트에게 전달


클라이언트 템플릿 엔진(ex-리액트, 뷰의 View 파일들)

  • Vue.js 나 React.js를 이용한 SPA(Single Page Application)는 브라우저에서 화면을 생성 (서버에서 이미 코드가 벗어난 경우)
  • 브라우저 위에서 작동,서버에서는 Json 혹은 Xml 형식의 데이터만 전달하고 클라이언트에서 조립


4.1.2 Mustache

많은 언어를 지원하는 심플한 템플릿 엔진으로서
자바에서 사용될 때는 서버 템플릿 엔진으로,
자바스크립트에서 사용될 때는 클라이언트 템플릿 엔진으로 모두 사용 가능



4.2 머스테치의 기본 사용 방법 / 스프링 부트에서의 화면 처리 방식

일단 의존성 추가

1
2
    implementation 'org.springframework.boot:spring-boot-starter-mustache'


머스테치의 기본 파일 위치는 src/main/resources/templates

  1. 첫 페이지를 담당할 index.mustache를 만들자 (간단히 글자 출력)
  2. URL을 매핑해야한다! Controller에서 진행, web 패키지 안에 IndexController 생성
1
2
3
4
5
6
7
@Controller
public class IndexController {

    @GetMapping("/")
    public String index() {
        return "index";
    }
  • mustache 스타터 덕분에 컨트롤러에서 문자열을 반환할 때 앞의 경로(src/main/resources/templates)뒤의 파일확장자(.mustache) 는 자동 지정
  • index.mustache로 전환 돼 View Resolver가 처리



4.3 js/css 선언 위치를 다르게 하여 웹사이트의 로딩 속도를 향상하는 방법


게시글 등록 화면을 만들자

부트스트랩, 제이쿼리 등 프론트엔드 라이브러리를 사용할 수 있는 방법은 크게 2가지

  1. 외부 CDN을 사용
  2. 직접 라이브러리를 받아서 사용

1번 방법은 외부 서비스에 우리 서비스가 의존하게 돼버려서 CDN을 서비스하는 곳에 문제가 생기면 같이 문제가 생길 수 있지만,
간단히 사용해보기 위해 1번 이용!


레이아웃 방식 으로 추가해보자
why? 공통 영역을 별도의 파일로 분리해서 필요한 곳에서 갖다 쓸 수 있도록 하려고


  1. src/main/resources/templateslayout 디렉토리 만들고 footer.mustache, header.mustache 파일 생성
1
2
3
4
5
6
7
8
9
10
// header.mustache
<!DOCTYPE HTML>
<html>
<head>
    <title>Spring boot Webservice</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>
1
2
3
4
5
6
7
8
// 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>


<script src="/js/app/index.js"></script>
</body>
</html>

:exclamation: 위의 두 코드를 보면 css와 js의 위치가 다르다

  • 페이지 로딩 속도를 높이기 위해 css는 header에, js는 footer에 (HTML은 위에서부터 코드가 실행되기 때문에 head가 다 실행되고 나서야 body가 실행됨)
  • 즉 head가 다 불러지지 않으면 사용자 쪽에선 백지만.. 특히 js의 용량이 크면 body 실행이 느려져서 body 하단에 둬서 화면이 다 그려진 후에 호출하자
  • css는 화면을 그리는 역할이므로 head에서 부르자
  • bootstrap.js 의 경우 제이쿼리가 있어야 해서, 부트스트랩보다 먼저 호출


  1. :exclamation: index.mustache 에 필요한 코드만 남기자
1
2
3
4
5
6
7
8
9
10
11
12

<h1>스프링 부트로 시작하는  서비스 Ver.2</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>


  • 는 현재 mustache 파일을 기준으로 다른 파일을 가져옴
  • 이동할 주소는 /posts/save 이고, 해당 컨트롤러를 만들자 -> 페이지 관련된 컨트롤러는 모두 IndexController에!
1
2
3
4
5
// 맨 위에 @RequiredArgsConstructor 추가
    @GetMapping("/posts/save")
    public String postsSave() {
        return "posts-save";
    }


  1. posts-save.mustache 파일 생성하자
    전체 코드
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    
        
        
     <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>
        
        
        
    


글 등록 버튼을 누르면
스크린샷 2023-01-16 오후 9 02 11


아직 API를 호출하는 JS가 없다!
src/main/resourcesstatic/js/app 만들고, index.js 생성!



4.4 js 객체를 이용해 브라우저의 전역 변수 충돌 문제를 회피하는 방법

머스테치가 아니더도 전에 잠깐 배웠던 Thymeleaf 나 Free-Marker 를 적용해봐도 좋겠다!

Date:

댓글남기기