본문 바로가기
JavaScript & TypeScript

Handlebar를 사용하여 배포까지 (+grunt +gradle)

by 향로 (기억보단 기록을) 2016. 6. 17.
반응형

현재 담당하고 있는 프로젝트에 기능이 추가되면서 개인적으로 공부도 할겸해서 기록으로 남기는 중이다.

기존 프로젝트에 이미 포함된 내용인데 내가 몰랐던 부분을 알게되면서 남긴거라 내가 이 기능을 사내 프로젝트에 넣었습니다!

이런건 아님을 먼저 알리며..

아래 내용의 모든 코드는 이미 Github에 올려져있다. 코드를 다 이미지로 찍어서 복붙으로 따라갈순 없으니 여기를 참고하자


사내에서 서비스하고 있는 프로젝트들은 IE 7,8을 공식 지원하고 있다.

그래서 요즘 유행하는 angular, react는 서비스 프로젝트에서는 쓰지 못하고 내부시스템에서만 사용하는 중인데, js 프레임워크들을 못쓰면서 경험하는 제일 큰 답답함이 클라이언트 템플릿 문제이다. 

(다른게 더 답답할수도 있음..)


클라이언트 템플릿이란 용어에 생소하다면 아래의 레거시(legacy) 코드를 보자.

(우리가 흔히 사용하는 Velocity나 프리마커 등은 서버사이드 템플릿엔진이며, 서버에서 DB 혹은 API에서 가져온 데이터와 함께 html을 그려서 전달해주는 방식이다.)



위 코드를 보면 서버쪽을 사용하지 않고 화면을 그리기(이하 렌더링) 위해 javascript로 html코드를 작성해서 추가해주고 있다.

계속해서 페이지를 이동하여 서버쪽 호출이 있다면 서버사이드 템플릿엔진을 사용하면 되는데, 단일 화면에서 특정 이벤트에 따라 화면이 계속 변경되어야 하는경우 이렇게 javascript로 html을 렌더링 하는 경우가 많다. 


근데 위 코드의 방식은 생각보다 많은 문제가 내포되어 있다.

1) html 코드에서 오타가 발생하는걸 찾을수가 없다. 왜냐하면 위 html 코드는 결국 문자열이기 때문에 </div> 태그가 1개 부족해도, 혹은 attribute가 오타가 나도 IDE에선 전혀 감지할수가 없다.

2) 렌더링 해야할 코드가 늘어나면 늘어날수록 수정 난이도가 급상승한다. 홀따옴표('), 쌍따옴표(") 만 가지고 표현할수가 없어 \ 를 붙이기 시작하면 이게 어떤 dom 형태가 될지 감이 안잡혀서 수정시간이 굉장히 길어진다.


(이것보다 더한 경우도 많다..) 


서론이 길었는데 결국 이런 문제를 해결하기 위해 등장한 것이 바로, handlebars 이다.

서버사이드 템플릿(JSP, 프리마커등) 엔진들처럼 html 형태로 코드를 작성할 수 있으며 동적으로 dom을 그리게 해주는 클라이언트 템플릿 엔진이다.


공식 사이트


기존에 국내 블로그에서 이미 handlebars의 문법과 튜토리얼이 워낙 잘되어 있어서 문법 같은 경우엔 해당 블로그들을 확인하면 될것 같다. (참고)


여기에서는 실제로 handlebars를 프로젝트에 적용하여 배포하는 방법을 진행하겠다. 

(생각보다 이걸 얘기해주는 국내 블로그가 없었다. 대부분 문법만 얘기해서 사내 코드에 있는 내용을 이해하는게 좀 힘들어서 나와 같은 고민을 하고 있는 사람이 있지 않을까하는 마음에 포스팅하게 되었다.)


간단하게 handlebars를 이용해서 위 코드를 수정해보겠다.

handlebars를 적용한 basic.html


이게 보통 기본적인 handlebars 를 사용하는 예제이다. text/x-handlebars-template 타입을 사용해서 템플릿이 가능한 코드로 지정하고, 이를 컴파일해서 사용한다.

보다시피 서버사이드 템플릿엔진과 유사하게 html형태를 유지하면서 원하는 형태의 dom을 렌더링할수가 있다.

코드를 작성하는 단계에서 오타를 미리 감지할수도 있으며, 어떤 dom 형태가 될지도 눈에 훤히 보인다.


하지만! 이것만 가지고 실제 프로젝트를 진행할순 없다. 

1) js와 html은 분리가 되어야한다는 것을 우리는 이미 알고 있다. (겸손한 자바스크립트)

2) js와 html을 분리해도 템플릿코드는 한곳에서 관리되어야 한다.


그래서 위 코드에서 템플릿 코드와 html 영역을 분리해보겠다.

이를 위해서는 grunt를 사용해야 한다. grunt가 뭔지, 어떻게 쓰는건지는 네이버의 널리 블로그를 참고하면 된다. 짱짱 잘 설명되어있다.

(gulp에서도 사용할수 있을것이다. grunt가 되는데 gulp가 안될리는 없으니.. 단지 회사에서 grunt를 사용해서 grunt로 예제를 만든것뿐이다.)  


grunt의 패키지 중 grunt-contrib-handlebars 를 이용하면 이 문제를 아주 쉽게 해결할수 있다.

grunt를 설치하고 npm으로 위 패키지를 설치하자.


package.json


Gruntfile.js


Gruntfile.js에서 설정하는 내용은 간단하다.

1) Handlebars.templates 라는 prefix를 붙이면 원하는 템플릿 코드를 사용 

2) grunt를 실행시키면 현재 handlebar 디렉토리에 포함된 모든 .handlebars 파일을 컴파일해서 templates.js에 추가


1) 내용이 이해가 안될텐데 아래 코드를 보자

현재 폴더 구조는 아래와 같다.


basic.handlebars와 basic2.handlebars 라는 2개의 handlebars 파일을 생성하였고, 이를 사용할 use-handlebar.html 파일을 생성하였다.

(basic.html과 helper.html은 무시해도 된다.)


basic.handlebars & basic2.handlebars


use-handlebar.html 


여기 부분이 핵심이다. 11라인에 보면 templates.js 를 호출한다.

이는 우리가 위 Gruntfile.js에 명시된 내용을 반영한것인데, grunt 명령어를 실행시키면 handlebars디렉토리 아래의 모든 handlebars 파일을 컴파일 하여 templates.js 가 생성되고 html에선 이를 호출하기만 하면 템플릿코드를 그대로 사용할수있다.

사용은 Handlebars.templates를 prefix로 하고, 뒤부터는 원하는 handlebars 파일의 이름을 명시하면 된다.

basic과 basic2라는 이름을 가진 handlebars 파일을 컴파일 했으니,  Handlebars.templates.basic & Handlebars.templates.basic2로 사용이 가능한 것이다.


본인이 프론트엔드 개발자라면 여기까지만 봐도 무방하겠지만 웹개발자라서 배포에 위 내용을 포함시키려면 결국 build까지 연동을 시켜야 한다. 백엔드의 build 예제는 gradle을 사용하였다. (마찬가지로 회사에서 gradle을 적극사용해서..)


Gradle을 모른다면 권남님의 블로그를 참고하자! 짱짱 설명이 잘되어있다.

우리가 할일은 gradle이 war를 만드는 build를 진행할때 grunt도 진행시켜 handlebars 파일을 pre-compile하는 것이다.

(코드는 Github에 있으니 불필요한 코드는 제외하고 봐야할 코드만 블로그에 남긴다.)


폴더구조



Gruntfile.js

Gruntfile은 compile 옵션만 변경되었다. result 파일과 target 폴더위치만 변경하였다.

 

build.gradle


build.gradle에 다른 내용은 변경할것이 없고, grunt라는 task가 새로 추가된것만 보면 된다. (나머지 스크립트는 Github 참고)

배포환경의 OS에 따라 grunt 커맨드를 입력하는 grunt 라는 task를 등록하고, 이를 빌드 process에 포함시킨다는 것이다.

이렇게 작성하면 우리는 war파일 혹은 jar파일로 build를 할때 grunt를 자동으로 실행시켜 templates.js가 생성되어 배포파일에 포함이 되므로 grunt 명령어를 배포때마다 입력할 필요가 없게 된다.


이 포스팅에 포함된 내용이 정답이 아닐수도 있다. 

다만 handlebars.js를 이렇게 사용할수도 있다? 클라이언트 템플릿 사용에 고민이 있다면 한번 참고하는것도 괜찮을것 같다. 



반응형