Mustache 템플릿 문법

수많은 언어에서 지원되는 초간단 템플릿 문법

Mustache는 제어 구조를 갖춘 것 중 (아마도) 가장 문법이 간단하고 (아마도) 가장 많은 언어로 포팅된 템플릿 엔진입니다. Mustache를 기반으로 이를 확장한 템플릿 엔진도 여럿 있는데 대표적으로는 헬퍼 개념을 추가한 Handlebars와 트위터에서 만든 Hogan.js를 들 수 있습니다.

이 문서는 Mustache 공식 문서를 기준으로 작성되었으며 예제도 해당 문서에서 가져왔습니다. 많은 스펙 문서가 그렇듯 Mustache의 템플릿 문법 문서에도 빈 부분이 많습니다. 스펙에는 없지만 구현체를 보고 동작을 ‘짐작’할 수 있는 부분에 대한 설명은 따로 글상자로 표기해두었습니다. 글상자 안에 있는 내용은 구현체마다 달라질 수 있으므로 사용 전에 확인이 필요합니다.

변수

{{}} 사이에 변수 이름을 입력합니다. 문자열은 자동으로 HTML 이스케이프가 되어 출력되는데 만약 이스케이프 되지 않은 문자열을 출력하고 싶다면 {{{}}}를 사용합니다. 참고로 Mustache는 구분자로 사용하는 {, } 기호가 콧수염 모양이라서 붙인 이름입니다. :)
데이터


{
  "name" : "Chris",
  "company" : "<b>Github</b>"
}

템플릿

* {{name}}
* {{age}}
* {{company}}
* {{{company}}}

결과

* Chris
* 
* &lt;b&gt;Github&lt;/b&gt;
* <b>Github</b>

두 번째 줄의 {{age}}age가 없는 변수이므로 아무런 값도 출력되지 않습니다. 네 번째 줄에서는 콧수염 세 개를 사용했기 때문에 HTML이 이스케이프 되지 않고 그대로 출력됩니다. 출력 결과를 웹 브라우저에서 보았다면 네 번째 줄은 굵은 글씨로 표시될 것입니다.

더 복잡한 객체 속성에 접근할 때

그러면 객체 안에 또 객체가 포함된 복잡한 객체에서 여러 단계를 거쳐야 하는 때는 어떻게 해야할까요? 예를 들어 앞에서 다룬 객체를 조금 확장한 다음과 같은 객체가 있다고 생각해봅시다.

{
  "name" : "Chris",
  "company" : {
    "name" : "Github",
    "address" : {
      "country" : "USA"
    }
  }
}

여기서 회사가 있는 국가에 접근할 때는 다음과 같이 자바스크립트의 점 문법(dot-syntax)를 사용합니다.

Country : {{company.address.country}}

위 템플릿 코드의 출력 결과는 다음과 같습니다.

Country : USA

섹션

섹션section 문법은 조건문이나 반복문 대신 사용됩니다. 주어진 값에 따라 조건문이나 반복문으로 사용되는데 {{#변수명}}으로 시작하고 {{/변수명}}으로 끝납니다. 변수가 배열이면 반복문으로 그렇지 않으면 조건문으로 사용되는데 0, false, 빈 문자열은 거짓으로 평가되므로 섹션의 내용이 출력되지 않습니다.

조건문

변수의 값이 배열이 아니면 조건문으로 사용됩니다. 단, 배열이라 하더라도 빈 배열은 거짓 조건문과 마찬가지로 취급되어 섹션의 내용이 출력되지 않습니다. 다음은 false 또는 비슷한 값을 변수로 사용했을 때의 결과입니다.
데이터


{
  "person" : false
}

템플릿

출력됩니다.
{{#person}}
  출력안됩니다.
{{/person}}

결과

출력됩니다.

변수가 객체라면 다음과 같이 사용할 수 있습니다.
데이터


{
  "person" : {"name" : "Jon"}
}

템플릿

{{#person}}
  {{name}}
{{/person}}

결과

  Jon

보다시피 섹션 안에서는 섹션 변수의 속성을 마치 변수처럼 사용할 수 있습니다.

섹션 내에서 다른 루트 변수에 접근할 때

위 코드를 보면 {{#person}} 섹션 안에서는 {{name}}을 통해 person.name에 접근했습니다. 그런데 person과 같은 수준에 있는 다른 변수가 있고 이 변수에 접근하고 싶다면 어떻게 해야할까요? 다음과 같은 객체가 있다고 생각해봅시다.

{
  "person" : {"name" : "Jon"},
  "company" : {"name" : "Google"}
}

템플릿은 다음과 같이 작성했습니다.

{{#person}}
  {{name}}의 회사는 {{???}}입니다.
{{/person}}

위 템플릿이 회사 이름으로 “Google”을 출력하려면 {{???}} 대신 {{company.name}}을 사용하면 됩니다. 템플릿 코드로 나타내면 다음과 같습니다.

{{#person}}
  {{name}}의 회사는 {{company.name}}입니다.
{{/person}}

하지만 Mustache의 확장 구현체인 Handlebars에서는 다음과 같이 사용하므로 주의가 필요합니다.

{{#person}}
  {{name}}의 회사는 {{../company.name}}입니다.
{{/person}}

반복문

변수의 값이 배열이면 반복문이 됩니다. 앞에서 말했듯이 빈 배열은 거짓 조건문으로 취급됩니다.
데이터


{
  "repo" : [
    { "name" : "resque" },
    { "name" : "hub" },
    { "name" : "rip" }
  ]
}

템플릿


{{#repo}}
  <b>{{name}}</b>
{{/repo}}

출력


  <b>resque</b>
  <b>hub</b>
  <b>rip</b>

반전 섹션

섹션과 반대되는 조건에서만 출력되는 블럭입니다. 즉, 섹션에 사용된 없는 변수이거나 변수의 값이 false 또는 이와 비슷한 값(0, 빈 문자열)이거나 빈 배열일 때만 출력됩니다. 반전 섹션은 {{^변수}}로 시작하고 {{/변수}}로 끝납니다.
데이터

{
  "repo": []
}

템플릿


{{#repo}}
  <b>{{name}}</b>
{{/repo}}
{{^repo}}
  저장소가 없네요. -_-
{{/repo}}

출력

  저장소가 없네요. -_-

주석

템플릿 코드에는 존재하지만 화면에는 출력되지 않는 코드를 작성할 때 사용합니다. 주석은 {{! 주석 }}과 같이 작성합니다. 다음과 같은 템플릿이 있다고 생각해봅시다.

<h1>Today{{! 여기는 안 나옵니다. }}</h1>

위 코드는 다음과 같이 출력됩니다.

<h1>Today</h1>

부분템플릿

부분템플릿(Partials)은 외부 파일을 템플릿의 일부로 불러올 수 있는 기능으로서 {{> 파일이름}}과 같이 사용합니다. 다음은 base라는 템플릿 파일에서 user라는 부분템플릿을 불러오는 예제입니다.

base.mustache 파일:
<h2>Names</h2>
{{#names}}
  {{> user}}
{{/names}}

user.mustache 파일:
<strong>{{name}}</strong>

위 코드는 사실 다음과 같은 하나의 템플릿 코드로 봐도 무방합니다.

<h2>Names</h2>
{{#names}}
  <strong>{{name}}</strong>
{{/names}}

템플릿 파일의 확장자는 구현체에 따라 달라질 수 있습니다.

구분자 설정

템플릿 태그를 시작하는 {{}}를 다른 구분자로 바꿀 수 있습니다. 구분자를 변경할 때는 {{=여는구분자 닫는구분자=}}와 같이 사용합니다. 다음은 구분자를 일시적으로 <% %>로 변경했다가 다시 {{ }}로 바꾸는 템플릿 코드입니다.

* {{default_tags}}
{{=<% %>=}}
* <% ERB_스타일_태그 %>
<%={{ }}=%>
* {{ 원래_템플릿_코드 }}

위 템플릿 코드는 두 번째 줄({{=<% %>>=}})과 네 번째 줄(<%={{ }}=%>)에서 구분자를 각각 <% %>{{ }}로 바꾸고 있습니다. TeX처럼 중괄호 두 개가 특수한 의미를 가지는 템플릿을 다룰 때 유용하다고 합니다.

Leave a Reply