HTML
, CSS
, JS
로 만든 웹 페이지를 서버에 접속하는 사용자의 브라우저에서도 보여주기 위해서는, 브라우저가 서버에서 HTML, CSS, JS 등 페이지를 이루는 파일을 다운받아 사용자의 화면에 구현해줘야 합니다.
이렇게 서버에 접속한 브라우저가 페이지를 구성하는 코드를 받아와서 내 브라우저에 원래 양식대로 구현해놓는 것을 렌더링
이라고 합니다.
Express 로 구현한 서버에서 템플릿 엔진
을 이용하여 HTML 렌더링을 하는 과정에 대해 알아봅시다.
PUG
템플릿 엔진을 이용한 렌더링 방법을 알아보겠습니다.
장점: 코드가 직관적이고 깔끔(들여쓰기로 계층 구분)
단점: PUG 문법을 따르므로 기존 html 문서와 호환이 어려움
※ 특징
1. 변수는 #{ } 안에 씀.
2. #{ } 안에 자바스크립트 코드 작성 가능.
3. - (하이픈) 을 앞에 쓰면 자바스크립트 코드 작성 가능.
4. html 처럼 태그를 열고 닫지 않음.
5. PUG 구문을 특정 형식과 함께 쓰지 않음.
npm install pug
PUG 를 설치해줍니다.
app.set("view engine" , "pug"); // 템플릿 엔진을 PUG 로 세팅
app.set("views", process.cwd() + "/views");
// process.cwd() 는 프로세스가 실행되는 위치
// views 폴더를 생성 후 그 위치 지정
// 렌더링 시 해당 디렉토리에서 템플릿을 찾게 됨
app 에서 view engine
을 세팅해줍니다.
이는 views 파일에서 확장자가 .pug 인 파일을 선택하겠다는 의미가 됩니다.
const controller = (req, res) => {
.
.
.
res.render("home", {text: "hello"});
}
// views 폴더에 있는 home.pug 파일을 렌더링
// home.pug 파일에 text 라는 변수를 보냄
app.get("/", controller);
이렇게 해주면 "/" 페이지로 접속했을 때 home.pug 파일이 화면에 나타납니다.
doctype html
html(lang="ko")
head
title PUG Page
body
main
span Hello
태그를 열고 닫지 않고, 태그 이름과 들여쓰기로 구분합니다.
속성은 ( ) 괄호 내부에 적어 사용합니다.
span.greeting.hello
// span 태그가 greeting, hello 클래스를 가짐
h1#mainTitle
// h1 태그가 mainTitle 아이디를 가짐
h1=pageTitle
// 태그 옆에 = 으로 변수 지정
h1 #{pageTitle}
// #{ } 내부에 변수 지정
h1 #{ new Date().getFullYear() }
// #{ } 내부에 자바스크립트 코드 사용
- const myTitle = "pug"
h1 #{myTitle}
// 하이픈 - 을 사용하여 정의한 로컬 변수 사용
doctype html
html(lang="ko")
head
title PUG Page
body
main
if user
h1 True
else if option
h1 ...
else
h1 False
doctype html
html(lang="ko")
head
title PUG Page
body
main
each message in messages
li=message
else
li No Message
// messages 라는 변수(배열) 에 값이 없다면 else 구문 실행
each val, index in [ ]
형태로 인덱스도 가져올 수 있습니다.
include 를 이용하면 다른 .pug 파일의 내용을 포함할 수 있습니다.
doctype html
html(lang="ko")
head
include partials/head
body
main
include partials/header
include partials/footer
// partials 폴더 내부의 .pug 파일들을 포함 중
include 가 작성된 부분에 파일의 내용이 포함됩니다.
.pug 파일이 아닌 텍스트 파일도 include 로 불러올 수 있습니다.
파일 상속 기능을 extends 를 통해 사용할 수 있습니다.
// layout.pug 파일 내용
doctype html
html(lang="ko")
head
title PUG Page
body
main
block content
// block 으로 상속받은 파일에서 재정의할 부분 지정
block 을 해주면 layout.pug 를 상속했을 때, 해당 부분을 재정의할 수 있습니다.
extends layout
block content
h1 This is content
// layout 파일의 block content 부분
이렇게 해주면, layout.pug 의 내용을 상속받고, content 부분에 block content 이하의 내용이 들어갑니다.
mixin 은 .pug 파일에서 함수처럼 사용할 수 있도록 재사용 가능한 코드 블럭을 만드는 것입니다.
mixin 은 다음과 같이 정의합니다.
mixin show(array)
each element in array
li=element
// 배열 매개변수를 받아 리스트 아이템으로 보여주는 mixin
show 라는 이름의 배열형 매개변수를 하나 받는 mixin 이 완성되었습니다.
mixin 을 사용하기 위해서는 + 기호
를 앞에 적어야 합니다.
ul
+show(list)
해당 위치에 mixin 의 내용이 삽입됩니다.
Nunjucks 템플릿 엔진을 이용한 렌더링 방법을 알아보겠습니다.
장점: 문서의 형식이 html 과 동일하여 호환이 편리
단점: 구문마다 {% %} 를 붙여줘야 해서 번거롭고 깔끔하지 않음
※ 특징
1. 구문 실행 시 {% %} 안에 코드를 넣어야 함.
2. 구문이 끝날 때마다 {% end~~ %} 라고 끝났다는 표시를 해줘야 함.
3. 변수는 {{ }} 안에 써야 함.
4. 자바스크립트 코드를 직접적으로 사용할 수 없음
npm install nunjucks
nunjucks 를 설치해줍니다.
import nunjucks from "nunjucks";
// 바벨 미설정이라면 const nunjucks = require("nunjucks");
app.set("view engine", "html"); // 확장자가 html 인 파일을 사용
app.set("views", process.cwd() + "/views");
// views 폴더가 위치한 경로 입력. 이 경로에서 템플릿을 찾음
nunjucks.configure(app.get("views"), {
autoescape: true,
express: app,
watch: true,
});
app 에서 view engine 을 세팅해줍니다.
const controller = (req, res) => {
.
.
.
const home = "my home";
res.render("home.html", {pageTitle: "HOME", home});
}
// views 폴더에 있는 home.html 파일을 렌더링
// 템플릿에 pageTitle 과 home 변수를 보냄
app.get("/", controller);
이렇게 해주면 "/" 페이지로 접속했을 때 home.html 파일이 화면에 나타납니다.
html 문서 형식을 그대로 사용합니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<header>
</header>
<main>
</main>
</body>
</html>
<h1>{{pageTitle}}</h1>
<a href="{{video.id}}/edit">Edit Video</a>
<!-- 속성에 변수를 사용할 땐 " " 안에 넣어줘야 함 -->
{% set fruit='apple' %}
<h1>I have {{fruit}}</h1>
<!-- set 을 사용하여 로컬 변수 선언 -->
변수는 {{ }}
내부에 적어 사용합니다.
속성 내부에 변수를 사용할 때는 " "
안에 같이 작성합니다.
set
을 사용하면 변수를 선언할 수 있습니다.
{% set num = 10 %}
{% if num > 10 %}
<h1>10 이상</h1>
{% elif num > 5 %}
<h1>5 이상</h1>
{% else %}
<h1>5 이하</h1>
{% endif %}
end
로 if 를 닫아줘야 한다는 특징이 있습니다.
조건문은 {{ }}
내부에서 간단하게 사용할 수도 있습니다.
<h1>{{ "사과" if fruit === "apple" else "사과가 아니네" }}</h1>
조건문에서 논리연산자는 영문으로 사용합니다.
(and, or, not)
for ~ in
문을 사용하며, 배열의 요소가 존재하지 않을 때의 경우를 위한 else
구문을 사용할 수 있습니다.
<ul>
{% for item in items %}
<li>{{ item.title }}</li>
{{ loop.index }} 번째
{% else %}
<li>'item' collection were empty</li>
{% endfor %}
</ul>
인덱스 번호는 loop.index
로 사용할 수 있습니다.
include 를 이용하면 다른 .nunjucks 파일의 내용을 포함할 수 있습니다.
{% include "item.html" %}
// 해당 부분에 item.html 문서의 내용을 삽입
상속 기능을 extends 를 통해 사용할 수 있습니다.
다른 .nunjucks 파일의 내용을 이어받아 사용합니다.
{% extends "base.html" %} // base.html 파일의 내용을 가져옴
{% block item %} // base.html 파일에 item 이라는 이름으로 block 된 부분을 대체
<h1>This is item</h1>
{% endblock %}
block 을 해주면 base.html 파일을 상속했을 때, 해당 부분을 재정의할 수 있습니다.
nunjucks 에서는 macro 를 사용하여 함수 기능을 구현합니다.
// myMacro.html 파일
{% macro field(name, value='', type='text') %}
<div class="field">
<input type="{{ type }}" name="{{ name }}"
value="{{ value | escape }}" />
</div>
{% endmacro %}
html 파일에 macro 를 정의합니다.
end
구문으로 macro 를 닫아줍니다.
{% from "myMacro.html" import field %} // myMacro.html 파일에서 field 매크로 가져오기
{{ field("name") }}
// {{ }} 안에 일반 함수와 같은 방법으로 매크로 사용
from 파일 import 매크로
로 매크로를 가져와 다른 파일에서 사용할 수 있습니다.
매크로는 {{ }}
내부에 일반 JS 함수처럼 사용합니다.