-
4장 ) 머스테치로 화면 구성하기Java & Spring/스프링 부트와 AWS로 혼자 구현하는 웹 서비스 2020. 7. 1. 01:26반응형
서버 템플릿 엔진과 머스테치 소개
- 템플릿 엔진
- 지정된 템플릿 양식과 데이터가 합쳐서 HTML 문서를 출력하는 소프트웨어
- 서버 템플릿 엔진 : JSP, Freemarker -> 서버에서 구동 ~> 브라우저로 전달
- 클라이언트 템플릿 엔진 : React, Vue -> 브라우저에서 화면 생성
- JSP, Velocity : Spring-boot에서 권장 X
- Freemarker - 과한 기능, 자유도가 높아서 숙련도가 낮을 수록 사용하기 힘들다.
- Thymeleaf - Spring에서 강하게 밀고있지만, 문법이 어렵다.
- 머스테치
- 서버 템플릿엔진, 클라이언트 템플릿 엔진으로 모두 이용 가능 (다양한 언어 지원)
- 장점
- 문법이 간단하다.
- View의 역할과 서버의 역할이 명확하게 분리된다.
- Mustache.js와 Mustache.java 2가지가 다 있어서, 하나의 문법으로 클라이언트/서버 템플릿 모두 이용 가능
- IntelliJ 에서 설치하기
- [ Ctrl + Shift + A ] -> plugins -> Market Place -> Mustache 검색
- Handlebars ~ 설치
- [ Ctrl + Shift + A ] -> plugins -> Market Place -> Mustache 검색
기본 페이지 만들기
의존성 등록하기
compile('org.springframework.boot:spring-boot-starter-mustache')
파일 기본 위치
- src/main/resources/templates가 기본 위치다.
- 이 위치에 두면, 스프링 부트에서 자동으로 로딩
위의 기본 위치에 index.mustache 만들기
<!DOCTYPE HTML> <html> <head> <title>스프링 부트 웹 서비스</title> <meta http-equiv="Content-Type" content ="text/html; charset=UTF-8"/> </head> <body> <h1>스프링 부트로 시작하는 웹 서비스</h1> </body> </html>
web 패키지 안에 IndexController 생성하기
package com.zin0.book.springboot.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class IndexController { @GetMapping("/") public String index(Model model) { model.addAttribute("posts", postsService.findAllDesc()); return "index"; } }
- 머스테치 스타터 덕분에 문자열을 반환할 때, 앞의 경로와 뒤의 파일 확장자는 자동으로 지정된다.
- 위의 경우 index를 기준으로 앞에는 src/main/resources/templates/ 가 붙고, 뒤에는 .mustache가 붙게 된다.
- 변환된 주소는 View Resolver가 처리한다.
test 패키지에 IndexControllerTest 클래스 생성하기
package com.zin0.book.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("스프링 부트로 시작하는 웹 서비스"); } }
게시글 등록 화면 만들기
- 프론트엔드 라이브러리를 사용하는 방법
- 외부 CDN을 사용
- 직접 라이브러리를 받아서 사용 (npm,webpack 등도 여기에 해당)
- 실제 서비스에서는 외부 서비스에 의존성을 줄이기 위해, 2번째 방법을 활용하지만, 지금은 토이 프로젝트가 목적이니까 외부 CDN을 이용함.
- 부트스트랩과 제이쿼리를 레이아웃 방식으로 추가하기
- 레이아웃 방식 - 공통 영역을 별도의 파일로 분리하여, 필요한 곳에서 가져다 쓰는 방식
- src/main/resources/templates 디렉토리에 layout 디렉토리를 추가로 생성
- 위의 디렉토리에 footer.mustache와 header.mustache를 생성한다.
스프링 부트 웹 서비스_Zin0 .another_category { border: 1px solid #E5E5E5; padding: 10px 10px 5px; margin: 10px 0; clear: both; } .another_category h4 { font-size: 12px !important; margin: 0 !important; border-bottom: 1px solid #E5E5E5 !important; padding: 2px 0 6px !important; } .another_category h4 a { font-weight: bold !important; } .another_category table { table-layout: fixed; border-collapse: collapse; width: 100% !important; margin-top: 10px !important; } * html .another_category table { width: auto !important; } *:first-child + html .another_category table { width: auto !important; } .another_category th, .another_category td { padding: 0 0 4px !important; } .another_category th { text-align: left; font-size: 12px !important; font-weight: normal; word-break: break-all; overflow: hidden; line-height: 1.5; } .another_category td { text-align: right; width: 80px; font-size: 11px; } .another_category th a { font-weight: normal; text-decoration: none; border: none !important; } .another_category th a.current { font-weight: bold; text-decoration: none !important; border-bottom: 1px solid !important; } .another_category th span { font-weight: normal; text-decoration: none; font: 10px Tahoma, Sans-serif; border: none !important; } .another_category_color_gray, .another_category_color_gray h4 { border-color: #E5E5E5 !important; } .another_category_color_gray * { color: #909090 !important; } .another_category_color_gray th a.current { border-color: #909090 !important; } .another_category_color_gray h4, .another_category_color_gray h4 a { color: #737373 !important; } .another_category_color_red, .another_category_color_red h4 { border-color: #F6D4D3 !important; } .another_category_color_red * { color: #E86869 !important; } .another_category_color_red th a.current { border-color: #E86869 !important; } .another_category_color_red h4, .another_category_color_red h4 a { color: #ED0908 !important; } .another_category_color_green, .another_category_color_green h4 { border-color: #CCE7C8 !important; } .another_category_color_green * { color: #64C05B !important; } .another_category_color_green th a.current { border-color: #64C05B !important; } .another_category_color_green h4, .another_category_color_green h4 a { color: #3EA731 !important; } .another_category_color_blue, .another_category_color_blue h4 { border-color: #C8DAF2 !important; } .another_category_color_blue * { color: #477FD6 !important; } .another_category_color_blue th a.current { border-color: #477FD6 !important; } .another_category_color_blue h4, .another_category_color_blue h4 a { color: #1960CA !important; } .another_category_color_violet, .another_category_color_violet h4 { border-color: #E1CEEC !important; } .another_category_color_violet * { color: #9D64C5 !important; } .another_category_color_violet th a.current { border-color: #9D64C5 !important; } .another_category_color_violet h4, .another_category_color_violet h4 a { color: #7E2CB5 !important; }
- 템플릿 엔진