2022.04.20 - [무조건 따라하기/java] - 스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - 3장 (2

 

스프링 부트와 AWS로 혼자 구현하는 웹 서비스 - 3장 (2)

 

whitewise95.tistory.com


04장 머스테치로 화면구성하기  


 

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

 


템플린 엔진의 종류와 단점

  • jsp, velocity : 스프링부트에서 권장하지 않는 템플릿 엔진
  • Freemarker : 과하게 많은 기능, 숙련도가 낮을수록 Freemarker안에 비지니스 로직이 추가 될 확률이 높습니다.
  • Thymeleaf
    스프링에서 적극적으로 밀고 있지만 문법이 어렸습니다. vue.js를 사용해 본 경험이 있어 태그속성 방식이 익숙한 분이라면 선택하셔도 됩니다.

머스테치의 장점

  • 문법이 다른 템플릿 엔진보다 심플합니다.
  • 로직 코드를 사용할 수 없어서 View의 역할과 서버의 역할을 명확하게 분리됩니다.
  • Mustache.js와 Mustache.java 2가지가 다 있어서, 하나의 문법으로 클라이언트/서버 템플릿 모두 사용 가능합니다.
  • 인텔리제이 커뮤니티버전에서도 플러그인을 사용할 수도 있습니다.

1. 플러그인 설치를 위해 mustache를 검색해서 해당 플러그인을 설치하면 됩니다. 설치가 완료되면 인텔리제이를 재시작하여 플러그인이 작동하는 것을 확인합니다.

2. 다음 코드를 gradle에 추가합니다.

implementation('org.springframework.boot:spring-boot-starter-mustache')

 

 

4.2 머스테치로 화면 구성하기


 1. 머스타치의 파일 위치는 src/main/resources/templates 가 기본 위치입니다. index.mustache를 생성합니다.

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
  <h1>스프링부트로 시작하는 웹 서비스</h1>
</head>
<body>

</body>
</html>

2. web패키지 안에 IndexController를 생성합니다.

package com.jojoldu.book.springboot.web;

import com.jojoldu.book.springboot.service.PostsService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@RequiredArgsConstructor
@Controller
public class IndexController {

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

}

3. 검증을 위해 test패키지에 IndexControllerTest를 생성합니다. 테스트까지 진행

package com.jojoldu.book.springboot.springboot.web;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT;

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = RANDOM_PORT)
public class IndexControllerTest {

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    public void 메인페이지_로딩() {
        //when
        String body = this.restTemplate.getForObject("/", String.class);

        //then
        assertThat(body).contains("스프링부트로 시작하는 웹 서비스");
    }
}

자신의 브라우저에서 접속도 해본다.

4.3 게시글 등록 화면 만들기


  1. 오픈 소스 부트스트랩 (CDN) 를 사용
  2. JQuery 사용
  3. 레이아웃방식으로 Header 와 Footer로 분리

1. templates 하위에 layout 패키지 생성 후 index.mustache에 layout 코드 작성

  1. footer.mustache , header.mustache 생성
  2. 부트스트랩, JQuery 코드 작성
  3. index.mustache에 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>

 

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>

 

index.mustache

{{>layout/header}}

<h1>스프링부트로 시작하는 웹 서비스</h1>


{{>layout/footer}}

{{>layout/header}} - {{>}}는 현재 머스테치 파일을 기준으로 다른 파일을 가져옵니다.

더보기

  페이지 로딩속도를 높이기 위해 css는 header에, js는 footer에 두었습니다. HTML은 위에서부터 코드가 실행되기 때문에 Head가 다 실행되고서야 body가 실행됩니다.  즉, head가 다 불러지지 않으면 사용자 쪽에선 백지 화면만 노출됩니다. 

 반면 css는 화면을 그리는 역활이므로 head에서 불러오느 것이 좋습니다. 그렇지 않으면 css가 적용되지 않은 깨진 화면을 사용자가 볼 수 있기 때문입니다. 

  부트스트랩의 경우 제이쿼리가 꼭 있어야만 하기 때문에 부트스트랩이 제이쿼리에 의존한다고 합니다.

2. 다음과 같이 수정하게됩니다.

  • index.mustache에 글 등록 버튼을 추가합니다.
  • IndexController에 글등록 메소드를 추가합니다.
  • 글 쓰는 페이지 posts-save.mustarche 를 생성합니다.

index.mustache

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

 

IndexController

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

 

posts-save.mustarche 

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

3. 브라우저에 localhost:xxxx/ 로 접근하고 글 등록이라는 버튼을 눌러 제대로 작동하는지 확인합니다.

4. src/main/resources에 stactic/js/app 디렉토리를 생성하고 index.js 파일를 생성합니다.

var main = {
    init : function () {
        var _this = this;
        $('#btn-save').on('click', function () {
            _this.save();
        });
    },
    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();

5. 자 그럼 생성된 index.js를 머스테치 파일이 쓸 수 있게 foorer.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>

6. 다음 과 같이 하겠습니다.

  • 글을 등록합니다.
  • localhost:xxxx/h2-console 에 접속하여 select* from posts  로 데이터를 확인합니다.

글을 등록합니다.
localhost:xxxx/h2-console 에 접속하여 select* from posts&nbsp;&nbsp;로 데이터를 확인합니다.

 

복사했습니다!