본문 바로가기
JavaScript

자바스크립트 템플릿 라이브러리 - handlebars

by enai 2019. 8. 9.

템플릿으로 HTML을 변경하는 작업을 할 때 도와주는 handlebars 라이브러리가 있다.

replace 메서드로 템플릿을 적용했던 기존 방법으론 템플릿 내용이 복잡하거나 길어질 수록 가독성도 떨어지고 코딩하기도 힘들다.

 

 

 

<html>
    <head>
        <style>
            li {
                list-style : none;
                padding: 3%;
                border-top: 1px solid gray;
            }
        </style>
    </head>
    <body>
        <h1>template using handlebar</h1>

        <section class="show">
          <script type="myTemplate" id="listTemplate">
            <li>
              <div>게시자 : {{name}}</div>
              <div class="content">{{content}}</div>
              <div>좋아요 개수 : <span> {{like}} </span></div>
              <div class="comment">
                  <div>{{comment}}</div>
              </div>
            </li>
          </script>
        </section>
    </body>
</html>

 

class가 show인 section 안에 게시글 목록을 만들 것이다.

section 태그 안에 템플릿을 만들어뒀다.

{{ }} 안의 내용과 매칭되는 데이터가 파싱될 것이다.

 

 

 

 

 

1. handlebars 설치

 

먼저 라이브러리를 사용하기 위해 설치를 해줘야 한다.

 

1) 구글에 handlebars cdn을 검색한다.

 

cdn은 content delivery network라는 뜻으로, 직접 다운로드 받지 않아도 가장 가까운 캐시 서버에서 컨텐츠를 가져와 사용할 수 있도록 해주는  기술이다.

 

 

2) 제일 처음 뜨는 사이트를 들어간다.

 

 

 

 

3) 4번째 줄 (https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.2/handlebars.min.js)에 마우스를 가져간다.

 

-> copy할 수 있는 버튼이 나타난다.

(min이 붙어있는 파일은 압축된 파일로 용량이 작다.)

 

 

4) 옆의 화살표를 누르면 뜨는 목록 중, Copy Script Tag를 클릭한다.

 

 

5) handlebars 라이브러리를 사용하려는 페이지에 복사된 태그를 붙여넣기 한다.

 

<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.2/handlebars.min.js" integrity="sha256-ngJY93C4H39YbmrWhnLzSyiepRuQDVKDNCWO2iyMzFw=" crossorigin="anonymous"></script>

 

 

 

 

2. handlebars 사용하기

 

1) handlebars 라이브러리로 템플릿을 가져온다.

 

var template = document.querySelector("#listTemplate").innerText;
var bindTemplate = Handlebars.compile(template);

 

querySelector라는 DOM API로 템플릿 내용을 가져와 handlebars 라이브러리로 컴파일한다.

handlebars의 compile 함수는 인자로 받은 템플릿의 문자열을 변수로 기억해뒀다가 데이터가 들어오면 알맞게 치환해주는 함수를 반환한다.

즉, 그 반환된 함수를 받은 bindTemplate 변수 역시 함수이다.

 

 

2) Handlebars.compile로 만든 함수에 (템플릿 속 문자를 치환해줄) 데이터를 넣어준다.

 

var data = {
  "id" : 16,
  "name" : "test",
  "content" : "새로운글을 올렸어요",
  "like" : 5, 
  "comment" : "댓글이다"
};

 

위의 데이터로 치환할 것이다.

 

var resultHtml = bindTemplate(data);

var show = document.querySelector(".show");
show.innerHTML = resultHtml;

 

Handlebars.compile로 만든 함수, bindTemplate에 data를 넣어주면 된다.

 

템플릿에 데이터를 넣어 만든 html 태그 결과물을 원하는 위치인 class가 show인 엘리먼트에 넣어준다.

 

 

결과물

 

 

 

 

3. 배열이 포함된 데이터 처리하기

 

만약 템플릿에 넣을 데이터에 배열이 있다면 어떻게 해야할까?

 

var data = {
  "id" : 16,
  "name" : "test",
  "content" : "새로운글을 올렸어요",
  "like" : 5, 
  "comment" : ["댓글이다", "멋진글이네요", "잘봤습니다"]
};

 

이럴 땐 템플릿에 반복문을 넣어 해결한다.

 

<script type="myTemplate" id="listTemplate">
  <li>
    <div>게시자 : {{name}}</div>
    <div class="content">{{content}}</div>
    <div>좋아요 개수 : <span> {{like}} </span></div>
    <div class="comment">
      <h4>댓글</h4>
      {{#each comment}}
      <div>{{@index}}번째 댓글 : {{this}}</div>
      {{/each}}
    </div>
  </li>
</script>

 

댓글 부분의 #each라고 적힌 부분을 보면 된다.

여기서 #은 헬퍼 기능으로, handlebars의 문법이다. # 옆에 적힌 건 예약어로 인식한다.

handlebars에선 each가 반복문을 의미한다. /each를 만날 때까지 반복이 일어난다.

 

@index는 for문의 i 값을 증가시키는 것처럼 증가되는 index값을 가져올 수 있다.

 

 

결과물

 

 

 

4. data 자체가 많은 경우 처리하기

 

var data = [
  {"id" : 16, "name" : "test", "content" : "새로운글을 올렸어요", "like" : 5, "comment" : ["댓글이다", "잘했어요"]},
  {"id" : 17, "name" : "singer", "content" : "전 오늘도 노래를 불렀어요", "like" : 0, "comment" : ["제발고만..","듣고싶네요 그노래"]},
  {"id" : 18, "name" : "okok", "content" : "크롱이 항상 말썽을 피워서 행복해~", "like" : 4, "comment" : []},
  {"id" : 19, "name" : "chicken", "content" : "물고기를 한마리도 잡지 못하다니..", "like" : 5, "comment" : ["댓글이다", "멋진글이네요", "잘봤습니다"]}
];

 

이렇게 데이터 자체가 많아서 배열로 되어있는 경우엔 forEach나 reduce로 쉽게 해결할 수 있다.

 

 

- forEach

 

data.forEach(function (item, index) {
	resultHtml += bindTemplate(item);
});

show.innerHTML = resultHtml;

 

 

- reduce

 

var resultHtml = data.reduce(function(prev, next) {
  return prev + bindTemplate(next);
}, "");

 

 

결과물

 

for문이나 map 등의 다른 반복 메서드로도 해결할 수 있지만 forEach와 reduce가 제일 간단하다.

특히 reduce는 누적 값을 처리하는 메서드로, 가장 적합한 용도로 사용된 것이다.

 

 

 

 

 

5. data에 값이 없는 경우 처리하기

 

댓글이 없는 경우 다른 메시지를 보여주도록 하려면 #if로 해결한다.

역시 handlebars에서 지원해주는 기능이다.

 

템플릿을 다음과 같이 바꿔준다.

 

<script type="myTemplate" id="listTemplate">
  <li>
    <div>게시자 : {{name}}</div>
    <div class="content">{{content}}</div>
    <div>좋아요 개수 <span> {{like}} </span></div>
    <div class="comment">
      <h4>댓글</h4>
      {{#if comment}}
        {{#each comment}}
          <div>{{@index}}번째 댓글 : {{this}}</div>
        {{/each}}
      {{else}}
        <div>댓글이 아직 없군요</div>
      {{/if}}
    </div>
  </li>
</script>

 

#if 옆에 적힌 값(comment)이 없으면 else 밑에 적힌 '댓글이 아직 없군요'가 파싱되도록 한다.

 

 

결과물

3번째 게시글에 댓글이 없어, '댓글이 아직 없군요' 메시지가 나타났다.

 

 

 

6. 커스텀 헬퍼 만들기

 

handlebars에서 기본으로 제공하는 헬퍼 외에도 커스텀으로 헬퍼를 만들 수 있다. 커스텀 헬퍼로 좀 더 다양한 상황을 처리할 수 있다.

 

좋아요 개수가 5개 이상일 때, "축하해요. 좋아요가 5개 이상입니다."라는 문자열이, 좋아요가 0개이면 "아직 아무도 좋아하지 않아요."라는 문자가 뜨도록 하려고 한다.

 

 

먼저 템플릿을 알맞게 수정한다.

 

<script type="myTemplate" id="listTemplate">
  <li>
    <div>게시자 : {{name}}</div>
    <div class="content">{{content}}</div>

    {{#likes like}}
    {{like}}
    {{/likes}}

    <div class="comment">
      <h4>댓글</h4>
      {{#if comment}}
        {{#each comment}}
          <div>{{@index}}번째 댓글 : {{this}}</div>
        {{/each}}
      {{else}}
        <div>댓글이 아직 없군요</div>
      {{/if}}
    </div>
  </li>
</script>

 

좋아요 부분을 수정했다.

 

좋아요 개수에 따라 다른 문자열이 나오도록 하는 헬퍼를 #likes라는 이름으로 만들려고 한다.

 

 

Handlebars.registerHelper("likes", function (like) {
  if (like > 4) {
    return "<span>축하해요. 좋아요가 " + like + "개 이상입니다.</span>";
  } else if (like < 1) {
    return "아직 아무도 좋아하지 않아요.";
  } else {
    return "좋아요 개수 <span>"+like+"</span>";
  }
});

 

커스텀 헬퍼는 handlebars의 registerHelper라는 메서드를 사용하여 만든다.

 

여기서 주의할 점은 handlebars로 템플릿 코드를 컴파일하는 코드보다 위에 있어야 한다는 것이다.

 

 

결과물

 

 

 

이처럼 헬퍼를 직접 만들어서 템플릿 처리를 좀 더 유연하게 할 수 있다.

 

 

 

each 헬퍼와 @데이터 변수 등을 사용해보고 추가 글을 작성했다.

중첩 데이터 바인딩하는 법이다.

handlebar 중첩 데이터 바인딩, @데이터변수

 

혹은 이 곳에서 handlebars.js에 대해 더 많은 것들을 알 수 있다. 원하는 기능의 내장 함수 등이 있는지 확인해보길 바란다.

 

 

 

 

 


 

 

handlebars 외에도 많은 템플릿 라이브러리가 있다.

(2019년 JavaScript 템플릿 라이브러리 top14 보러가기)

 

또, ES2015의 template literal에서 제공하는 tagged template Literals라는 것도 있다.

 

 

 

 

 

 

 

출처)

edwith 부스트코스 웹 프로그래밍

- handlebars를 활용한 템플릿 작업

댓글