Node.js/Express Pug(view engine)-2
05 May 2021Pug에서는 파일 내부 구조를 효과적으로 나누고 합칠 수 있도록 다양한 키워드들을 제공해 준다.
views를 만들다 보면 head나 footer등과 같은 layout, 또는 필수 script 등은 모든 파일에 들어가야 하므로 코드가 중복되게 되는데 이를 크게 줄이면서, 각 태그의 기능별로 코드를 쪼개어 views 파일들도 모듈화하는 느낌을 줌으로써 추후 유지보수에도 좋고 가독성도 높일 수 있다.
예시를 위한 디렉토리 구조
├──node_modules
├─┬src
│ ├─┬controllers
│ │ ├──userController.js
│ │ └──videoController.js
│ ├─┬routers
│ │ ├──globalRouter.js
│ │ ├──userRouter.js
│ │ └──videoRouter.js
│ └─┬views <---------------------
│ ├─┬partial
│ │ └──footer.pug
│ ├──base.pug
│ ├──home.pug
│ └──watch.pug
├──server.js
└──pakage.json
☄ Includes
https://pugjs.org/language/includes.html
한 Pug 파일의 내용을 다른 Pug 파일에 삽입할 수 있다.
footer는 거의 모든 파일에 들어가는 태그이며 내용이다. 따라서 이 코드만 따로 파일로 만들어서 include하면 중복도 줄이고 수정할 일이 생길 때 footer.pug만 수정하면 되기 때문에 매우 효율적이다.
// home.pug
doctype html
html(lang="ko")
head
title Wetube
body
h1 Welcome to Wetube
include partials/footer.pug
// watch.pug
doctype html
html(lang="ko")
head
title Wetube
body
h1 Watch video
include partials/footer.pug
// partials/footer.pug
footer © #{new Date().getFullYear()} Wetube
#{} 문법은 .pug에서 JavaScript 코드를 사용할 수 있게 해준다.
위 코드에서는 현재 년도를 가져와 넣어 준다.
☄ Inheritance: Extends and Block
https://pugjs.org/language/inheritance.html
Pug는
Extends와Block키워드로 템플릿 상속을 지원한다.
include를 사용하더라도 중복되는 코드가 많이 발생하고 include 조차 중복해서 작성해 줘야 된다. 그렇다고 모두 개별적으로 .pug파일을 만들어 관리하기도 오히려 더 복잡해 지는 느낌이 있다.
이때 사용하면 좋은 키워드가 Extends와 Block 키워드다. html은 기본적으로 필수 태그들이 존재하고, 개발자가 원하는 base layout이 존재하기 마련이다. 이를 하나의 파일에 작성하고 Extends 키워드를 이용해 다른 파일들에서 가져다 쓸 수 있다.
단, include와의 차이점은 Extends 의미에서 처럼 단순히 가져다 쓰는 것이 아니라 내부 코드에 Block 키워드를 이용해서 각 파일별로 필요한 코드들을 원하는 위치에 추가하는 식으로 확장할 수 있다.
때문에 다른 .pug 파일을 마치 상속해서 사용하기 때문에 템플릿 상속을 지원한다는 설명이 붙여있다.
// base.pug
doctype html
html(lang="ko")
head
block head
body
block content
include partials/footer.pug
// home.pug
extends base.pug
block head
title home | WeTube
block content
h1 This is home !

// watch.pug
extends base.pug
block head
title watch | WeTube
block content
h1 Watch Video !

☄ Pug 템플릿에서 Variables 사용하기
컨트롤러에서 렌더링 할 .pug 파일에서 사용할 수 있도록 객체(변수)들을 넘겨줄 수 있다.
Response.render(view: string, options?: object, callback?: (err: Error, html: string) => void): void
예를 들어 위 예제에서 title 태그를 보면 타이틀 | WeTube 부분이 중복된다. block head를 다른 파일에서 지우고 base.pug에서 템플릿 변수를 이용해 한 번에 처리할 수 있다.
// videoController.js 일부분
export const trending = (req, res) => res.render("home", { pageTitle: "home" });
위와 같이 res.render의 두 번째 인자에 템플릿에서 사용할 변수를 object로 속성과 값으로 지정해 넘겨 준다.
// base.pug
doctype html
html(lang="ko")
head
head #{pageTitle} | WeTube
body
block content
include partials/footer.pug
// home.pug
extends base.pug
block content
h1 This is home !