11-18 19:33
Notice
Recent Posts
Recent Comments
관리 메뉴

Scientific Computing & Data Science

[Programming / WebApp] Express Template Engine / Pug 본문

Programming/Web App

[Programming / WebApp] Express Template Engine / Pug

cinema4dr12 2016. 9. 3. 00:01

"Pug"는 Express Framework의 Template Engine으로 이전에 "Jade"라는 이름을 가지고 있었으나, "Jade"가 상표권이 걸려 있어 부득이하게 "Pug"라는 이름으로 개명(?)하게 되었다.
따라서, 기존의 "Jade" 문법에 익숙한 개발자들은 "Pug"에 금방 익숙해 질 수 있다.
간단하게 Pug의 문법과 활용법에 대하여 살펴보도록 하자.

Pug 설치하기

여타 Node Packages처럼 Command Line Tool의 "npm" 명령을 통해 Pug Node Package Manage로 설치가 가능하다.

$ npm install pug

또는 Node.js의 최신 버전이 설치되어 있으면,

$ npm install pug-cli -g

과 같이 명령을 입력하면 된다.

위의 설치 옵션 "-g"는 자신의 Local Machine에 전역적으로 설치하는 옵션이며, 만약 프로젝트 단위로 설치를 원한다면,

$ npm install --save pug

를 입력하거나, package.json 파일에 정의하여 "npm install" 명령을 통해 프로젝트 폴더에 로컬로 설치가 가능하다.
가령, 다음과 같이 package.json 파일에 "dependencies"에 설치하고자 하는 Pug의 버전을 명시할 수 있다.

[package.json]

{

  "dependencies": {

    "pug": "2.0.0"

  }

}


Quick Start

우선 Express 프로젝트가 준비되었다고 가정한다. 만약 Express 프로젝트 생성하는 방법은 Express 웹 어플리케이션 템플릿 작성을 참고하기 바란다.

프로젝트 Root 경로에 있는 app.js 파일에 다음 코드를 추가한다.

app.js

var express = require('express');
var routes = require('./routes/index');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use('/', routes);


routes 폴더에 다음과 같이 index.js 파일을 작성한다.


index.js

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function (req, res) {
  res.render('index',
  {
    title: 'Hey',
    message: 'Hello there!'
  } );
} );

module.exports = router;

views 폴더에 index.pug 파일을 생성하고 다음과 같이 작성한다.

index.pug


doctype html
html(lang="en")
    head
        title= title
    body
        p.greetings#people #{message}


이제 서버를 실행하면 다음과 같이 페이지가 뜨게 된다.


 


위의 이미지의 개발자 도구를 통해 볼 수 있듯이, 렌더링 된 페이지는 다음과 같이 변환되었음을 알 수 있다.


<!DOCTYPE html>
<html>
    <head>
        <title>Hey</title>
    </head>
    <body>
        <p class="greetings" id="people">Hello there!</p>
    </body>
</html>


여기서 주목할 것은, index.js에서 .greetings와 #people은 각각 classid 태그 속성을 의미한다.


Text 작성

텍스트를 태그에 삽입하는 방법은 3가지가 있다.

1. 태그 + 공란을 포함한 텍스트

포맷:


{TAG} {TEXT}


예:


h1 hello, welcome to pug

2. 태그 + 파이프 텍스트

포맷:


{TAG} 
      | Line 1 
      | Line 2
      | ...


예:


div
	| To insert multiline text,
	| You can use the pipe operator.

3. 태그 + 텍스트 블럭

포맷:


{TAG}.
        Line 1
        Line 2
        ...

예:


div.
	But that gets tedious if you have a lot of text.
	You can use "." at the end of tag to denote block of text.
	To put tags inside this block, simply enter tag in a new line and
	indent it accordingly.


주석

HTML Document에서는 일반적으로 주석(Comment) 삽입 시, <!-- comment --> 형식으로 작성한다.

Pug에서는 JavaScript에서는 주석을 작성하는 형식으로 한다.

즉, 다음 코드는


//This is a Pug comment


아래 코드와 같이 변환된다.


<!--This is a Pug comment-->


태그 속성

1. class


{TAG}.{class1}.{class2}.{class3}...


예를 들어, 다음 코드는,


div.container.column.main


아래와 같이 변환된다.


<div class="container column main"></div>

2. id

{TAG}.{#id}

예를 들어, 다음 코드는,


div#division


아래와 같이 변환된다.


<div id="division"></div>

3. 기타 속성

{TAG}({attr_1}="{value_1}", {attr_2}={"value_2"})


예를 들어, 다음 코드는,


div(width="100%",height="100%")


아래와 같이 변환된다.


<div width="100%" height="100%"></div>


값 전달하기

다음의 JavaScript 코드와 같이 페이지 렌더링을 위해 전달할 값(title, message, url)을 정의한다.


router.get('/', function (req, res) {
  res.render('index',
  {
    title: 'Hey',
    message: 'Hello there!',
    url: 'http://cinema4dr12.tistory.com'
  } );
} );


Pug 파일에서는 전달받은 값을 다음과 같이 처리한다.


doctype html
html(lang="en")
    head
        title= title
    body
        p.greetings#people #{message}
        a(href= url, target= "blank") cinema4dr12.tistory.com


조건문

페이지 렌더링 시 조건문을 지원한다는 것은 웹 어플리케이션 구현에 있어 매우 유용하다.

Pug의 조건문은 매우 깔끔하다.

1. if Statement

if ({condition}})
    // do somethimg when the condition meets
else if ({other condition})
    // do somethimg when other condition meets
else
    // do something otehrwise


예를 들어, JavaScript의 페이지 렌더링 옵션을 다음과 같이 작성하면,


router.get('/', function (req, res) {
  res.render('index',
  {
    title: 'Hey',
    user: {
        name: "Geol Choi",
        age: "40"
    }
  } );
} );


Pug 페이지에서는 user 값이 있는지 확인하고 값을 이용하여 페이지에 표시하도록 한다.


doctype html
html(lang="en")
    head
        title= title
    body
        a(href= url, target= "blank") cinema4dr12.tistory.com
        br
        if(user)
            h1 Hi, #{user.name}, your age is #{user.age}
        else
            a(href="/sign_up") Sign Up

2. case-when Statement

case-when 문은 일반적인  코딩에서 switch-case 문이라고 생각하면 된다.

문법은 다음과 같다.


case friends
  when {CASE_1}
    // do something for CASE_1
  when {CASE_2}
    // do something for CASE_2
  default
    // do something for default case


예를 들어, JavaScript 파일에 다음과 같이 작성하고,


router.get('/', function (req, res) {
  res.render('index',
  {
    title: 'Hey',
    message: 'Hello there!',
    url: 'http://cinema4dr12.tistory.com',
    friends: 2
  } );
} );


Pug페이지에 friends에 대하여 다음과 같이 처리한다.


doctype html
html(lang="en")
    head
        title= title
    body
        a(href= url, target= "blank") cinema4dr12.tistory.com
        br
        case friends
          when 0
            p You have no friends.
          when 1
            p You have a friend.
          when 2
            p You have two friends.
          default
            p You have #{friends} friends.


페이지 렌더링 결과는 다음과 같다.



반복문

반복문 역시 매우 중요한 문법 중의 하나이며, 특히 목록을 표시하는데 있어 매우 유용한데 Pug에서는 반복문이 어떻게 구현되는지 살펴본다.

1. each 문

일반적인 코딩에서 for 문이라고 생각하면 되겠다.

몇가지 예를 들어 보겠다.


[Example 1]


ul
  each val in [1, 2, 3, 4, 5]
    li= val

결과는,


<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
</ul>


[Example 2]


ul
  each val, index in ['zero', 'one', 'two']
    li= index + ': ' + val

결과는,


<ul>
  <li>0: zero</li>
  <li>1: one</li>
  <li>2: two</li>
</ul>


만약 회원 관리 페이지를 작성한다면 회원 멤버를 JSON 값을 전달하고, 이를 each 문을 통해 출력한다.

예를 들어, JavaScript 파일에서는,


router.get('/', function (req, res) {
  res.render('index', {
    title: 'Hey',
    message: 'Hello there!',
    url: 'http://cinema4dr12.tistory.com',
    users: {
      user_1: {name: "gchoi", age: "40"},
      user_2: {name: "jmpark", age: "28"},
      user_3: {name: "tjkwak", age: "34"},
      user_4: {name: "hskim", age: "40"},
      user_5: {name: "jhlee", age: "39"},
      user_6: {name: "dwsuh", age: "35"}
    }
  } );
} );


과 같이 작성하고, Pug 파일에서는,


doctype html
html(lang="en")
    head
        title= title
    body
        a(href= url, target= "blank") cinema4dr12.tistory.com
        br
        ul
            each val, index in users
                li= 'Name: ' + val.name + ', Age: ' + val.age


과 같이 작성하면 다음과 같은 결과를 얻을 수 있다.


2. while 

[Example]


doctype html
html(lang="en")
    head
        title while statement
    body
        - var n = 0;
        ul
          while n < 4
            li= n++


은 다음과 같이 변환된다.


<ul>
  <li>0</li>
  <li>1</li>
  <li>2</li>
  <li>3</li>
</ul>


Script Tag

HTML 기반의 웹 어플리케이션 작성에 있어 <script> 태그는 가장 중요한 태그 중 하나이다. 문법은 다음과 같다.


script(src={SCRIPT_PATH})


예를 하나 들면 매우 이해가 쉬울 것이다.


head
  script(src='/vendor/three.js')
  script(src='/game.js')


Include

Pug의 include 키워드는 다른 pug 파일을 포함시키는 경우에 사용한다. 예를 들어, head.pug 파일을 다음과 같이 작성하고,


head
    title= title


body.pug 파일을 다음과 같이 작성하고,


body
    a(href= url, target= "blank") cinema4dr12.tistory.com
    br
    ul
        each val, index in users
            li= 'Name: ' + val.name + ', Age: ' + val.age


동일한 경로 내에 index.pug 파일을 다음과 같이 작성하면,


doctype html
html(lang="en")
    include ./head.pug
    include ./body.pug


실제로는 index.pug 파일은


doctype html
html(lang="en")
    head
        title while statement
    body
        a(href= url, target= "blank") cinema4dr12.tistory.com
        br
        ul
            each val, index in users
                li= 'Name: ' + val.name + ', Age: ' + val.age

과 같다.


템플릿 상속

Pug의 extends 키워드는 block을 지정하고 지정된 block을 확장할 수 있도록 한다.


예를 들어, layout.pug를 다음과 같이 작성하고,


layout.pug

doctype html
html(lang="en")
head
    head
        title #{title}
    body
        a(href= url, target= "blank") cinema4dr12.tistory.com
        br
        ul
            each val, index in users
                li= 'Name: ' + val.name + ', Age: ' + val.age
        block content


index.pug를 다음과 같이 작성하면,


index.pug

extends ./layout.pug

block content
    h1 This content is extended.


렌더링된 페이지의 결과는 다음과 같다.


 

마지막으로 extends prepend / append에 대하여 살펴보고자 한다.

append는 지정된 block을 확장할 때 원래의 block의 다음 항목으로 확장한다.

예를 들어,


layout.pug

html
  head
    block head
      script(src='/vendor/jquery.js')
      script(src='/vendor/caustic.js')
  body
    block content


index.pug

extends layout.pug

block append head
  script(src='/vendor/three.js')
  script(src='/game.js')


는 다음과 같은 페이지로 렌더링 된다. (script 나열 순서에 유의)


html
  head
    block head
      script(src='/vendor/jquery.js')
      script(src='/vendor/caustic.js')
      script(src='/vendor/three.js')
      script(src='/game.js')


만약 append 대신 prepend 키워드를 사용하였다면, 다음과 같은 페이지로 렌더링 될 것이다.


html
  head
    block head
        script(src='/vendor/three.js')
        script(src='/game.js')
        script(src='/vendor/jquery.js')
        script(src='/vendor/caustic.js')


Pug를 이용하여 웹 페이지 설계 시 유용한 웹 사이트를 하나 소개하고자 한다.

바로 HTML 문서를 Pug 문서로 변환해 주는 사이트이다: http://html2pug.com

그리고, Atom 유저라면 Pug의 Syntax Highlighter인 language-pug를 설치하면 개발하기에 매우 편리하다.

Comments