[혼자 구현하는 웹 서비스] 4장 머스테치로 화면 구성

2020. 7. 8. 16:55책/스프링 부트와 AWS로 혼자 구현하는 웹 서비스

 

4장 머스테치로 화면 구성

책이 아닌 강의로 스프링 공부를 할 때, 화면 구성을 위해서 Thymeleaf를 많이 사용하였다. 

화면 구성 자체가 관심 분야가 아닌 탓인지, 문법이 어려운 탓인지 흥미가 잘 가지 않았었다.

이해하며 작성하기 보단, 그때그때 필요한 내용을 검색하여 무작정 사용한 적이 많았던 것 같다.

머스테치는 그보다 훨씬 간단해서 사용하기 편하다고 하니 열심히 공부해서,

잘 사용하는 템플릿 엔진으로 만들고 싶다.

1. 서버 템플릿 엔진과 머스테치

일반적으로 웹 개발에 있어 템플릿 엔진이란, 지정된 템플릿 양식과 데이터가 합쳐져 HTML 문서를 출력하는 소프트웨어를 이야기한다. 그렇다면, 서버 템플릿 엔진은 말 그대로 서버 측에서 동작하는 템플릿 엔진이다. 대표적으로 JSP, Freemarker를 떠올릴 수 있겠다. ( JSP는 템플릿 엔진은 아니지만 단순히 view의 역할만 하도록 구성할 때는 템플릿 엔진이라고 볼 수 있다고 한다.)

서버 템플릿 엔진이 있다면 클라이언트 템플릿 엔진이 있는데, 대표적으로 뷰나 리액트의 view파일을 예로 들 수 있다. 두 차이점은 html문서를 어느 곳에서 생성하느냐의 차이이다. (리액트를 주력으로 하는 친구와 프로젝트를 하기 위해서는 리액트의 서버 사이드 렌더링을 이용해야 하는데, 리액트 + 스프링 부트 프로젝트를 하려면 자바스크립트 프레임워크와 스프링 부트에 대한 이해도가 높아져야 가능하겠다.)

 

머스테치는 수많은 언어를 지원하는 가장 심플한 템플릿 엔진이다.

스프링 공부를 하며 Thymeleaf 템플릿 엔진을 사용해 보았었는데, 두 템플릿 엔진의 특징을 정리해보면 다음과 같다.

 

  • Thymeleaf : 스프링 진영에서 적극적으로 밀고 있지만 문법이 어렵다. HTML 태그에 속성으로 템플릿 기능을 사용하는 방식이 기존 개발자들에게 높은 장애물로 느껴지는 경우가 많다.
  • 머스테치 : 문법이 다른 템플릿 엔진보다 심플하다. 로직 코드를 사용할 수 없어서 view의 역할과 서버의 역할을 명확하게 분리하게 한다.

이 책에서는 템플릿 엔진은 오로지 화면 역할에 충실하도록 하기 위해 머스테치를 사용하였다.

( + 다른 템플릿 엔진이 인텔리제이 얼티메이트 버전에서만 지원하는 반면, 머스테치는 커뮤니티 버전을 통해서도 플러그인을 사용할 수 있다.)

 

2. 기본 페이지 만들기

먼저, 머스테치를 사용하기 위해 머스테치 스타터 의존성을 추가한다.

보이는 것처럼 머스테치는 스프링 부트에서 공식 지원하는 템플릿 엔진이다.

머스테치의 파일 위치는 기본적으로 'src/main/resources/templates' 이다. 이 위치에 머스테치 파일을 두면 스프링 부트에서 자동으로 로딩하게 된다. 해당 위치에 index.mustache 파일을 만들고 컨트롤러를 통해 URL을 맵핑해준다.

 

머스테치 스타터 덕분에 컨트롤러에서 문자열을 반환할 때 앞의 경로와 뒤의 파일 확장자는 자동으로 지정되게 된다. (Thymeleaf와 마찬가지) 여기에서는 index를 반환하므로, src/main/resources/templates/index.mustache로 전환되어 View Resolver가 처리하게 된다.

 

테스트 코드를 통해 확인해보면 잘 통과되는 것을 볼 수 있었다.

 

3. 게시글 등록 화면

앞서 PostsApi를 구현하였기 때문에, 화면을 개발하여 확인해보는 작업을 해보겠다.

HTML파일만으로는 디자인 적으로 너무 볼품 없기 때문에, 오픈소스인 부트스트랩을 이용하여 화면을 만든다.

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

하나는, 외부 CDN을 사용하는것이며, 다른 하나는 직접 라이브러리를 받아서 사용하는 방법이다.

여기서는 외부 CDN을 사용한다.(더 쉽다... 하지만 실제 서비스에서는 이 방법을 잘 사용하지 않는데, 이 방법은 외부의 서비스에 의존하는 것이므로, CDN을 서비스하는 곳에 문제가 생기면 덩달아 같이 문제가 생길 수 있기 때문이다.)

 

2개의 라이브러리인 부트스트랩과 제이쿼리를 index.mustache에 추가해야 하는데, 레이아웃 방식으로 추가해 본다.

레이아웃 방식으로 추가하는 것은 공통 영역을 별도의 파일로 분리하여 필요한 곳에서 가져다 쓰는 방식을 뜻한다.

(css에서도 코드의 재사용을 위해 css파일을 따로 두고 적용시키듯, 머스테치 화면 어디서나 필요한 내용을 별도의 파일로 만들어 두고 적용시키는 방식이라고 할 수 있다.)

 

src/main/resources/templates에 layout폴더를 만들고 그곳안에 공통으로 사용할 mustache파일을 만든다.(header.mustache, footer.mustache)

 

 

 

이후 index.mustache를 다음과 같이 수정할 수 있다.

{{> }}는 현재 머스테치 파일을 기준으로 다른 파일을 가져오는 의미이다. 즉, h1위에는 header.mustache에 내용을 옮기고 h2밑으로는 footer.mustache에 내용을 옮긴다음 위와 같은 코드를 적어줄 수 있는 것이다.

 

게시글 화면의 UI를 구성했다면, 기존에 만들어 두었던 API를 호출하는 JS를 만들어 주어야 한다.

src/main/resources에 static/js/app 디렉토리를 생성한후, index.js를 생성하여 내용을 넣어준다.

 

 

위에서 var main={...}는 index.js만의 유효범위를 만들어 사용하는 것이다. 이렇게 하면 index 객체 안에서만 function이 유효해지기 때문에 다른 js와 겹칠 위험이 사라진다. (예를들어 분업도중엔 함수이름이 겹칠 일이 많아지는데, 이러한 문제를 해결할 수 있다.)

 

만든 index.js를 머스테치 파일이 사용할 수 있도록 footer.mustache에 

<script src="/js/app/index.js"></script>를 추가해준다.

( 호출 경로를 보면 "/"로 바로 시작하는데, 스프링 부트는 기본적으로 src/main/resources/static에 위치한 자바스크립트, css, 이미지 등의 정적파일들을 "/"로 설정한다.)

위와 같이 등록 버튼이 활성화 되고 잘 작동하는 것을 확인할 수 있다. 

게시글 조회를 위해 다음과 같은 머스테치 문법을 사용하여 화면을 구성한다.

 

1. {{#posts}} : posts라는 List를 순회한다. java의 for문과 동일하게 생각하면 된다.

2. {{id}}  등의 {{변수명}} : list에서 뽑아낸 객체의 필드를 사용한다.

 

Controller, Service, Repository작성

 

규모가 있는 프로젝터에서의 데이터 조회는 FK의 조인, 복잡한 조건 등으로 인해 이런 엔티티 클래스만으로 처리하기가 어렵다. 따라서 조회용 프레임워크를 추가로 사용하는데 이 책에서는 querydsl를 추천하고 있다. 이유는 타입안정성이 보장되며, 많은 레퍼런스가 존재하기 때문이라고 한다. 

 

Service에는 다음과 같은 메소들를 추가한다.

위와같이 readOnly = true를 옵션으로 추가해주면 트랜잭션 범위는 유지하되 조회 기능만 남겨두어 조회 속도가 개선된다고 한다. 등록, 수정, 삭제 기능이 전혀 없는 서비스 메소드에서 사용하면 좋겠다. 위 코드는 postsRepository 결과로 넘어온 posts의 stream을 맵을 통해 리승트로 반환하는 메소드 이다. PostsListResponseDto는 화면에 보여줄 정보를 가진 엔티티로 생성해준다.

 

 

controller

컨트롤러의 기본 화면을 위와같이 구성해준다. 

Model은 서버 템플릿 엔진에서 사용할 수 있는 객체를 저장할 수 있는데, 여기서는 postsService.findAllDesc()로 가져온 결과를 index.mustache에 전달하는 역할을 한다. 위와같이 코드들을 구성하면 글 등록과 화면에 표시가 잘 이루어지는 것을 확인할 수 있다.

 

그 외에 수정/삭제는 기존에 만들었던 API 컨트롤러를 이용해서 구현하였다.