오늘은 PUG(옛날 이름 JADE)에 대해서 간단히 소개해보고자 합니다.
1. Pug란 무엇인가?
Pug(이전 이름: Jade)는 Node.js 기반의 HTML 템플릿 엔진입니다. 쉽게 말하면, 간결한 문법으로 HTML을 생성할 수 있게 도와주는 도구로, 코드의 가독성을 높이고 유지보수를 용이하게 하는 툴입니다.
Node.js 기반이기 때문에 백엔드 작업에서 주로 사용되지만, 정확히는 템플릿 엔진이라는 점에서 HTML 생성이 필요한 모든 작업에서 유용하게 쓰일 수 있습니다.
2. 왜 Pug를 사용해야 할까?
(1) 간결한 문법
Pug는 중첩 구조를 들여쓰기로 표현합니다. 이를 통해 불필요한 태그나 중복된 닫는 태그 없이 깔끔하게 HTML 코드를 작성할 수 있습니다.
doctype html
html
head
title Pug 예제
body
h1 안녕하세요, Pug입니다!
p Pug를 사용하면 HTML 작성을 간소화할 수 있어요.
예를 들어, PUG 파일에서 다음과 같이 작성한 것은
<!DOCTYPE html>
<html>
<head>
<title>Pug 예제</title>
</head>
<body>
<h1>안녕하세요, Pug입니다!</h1>
<p>Pug를 사용하면 HTML 작성을 간소화할 수 있어요.</p>
</body>
</html>
html을 위처럼 작성한 것과 동일합니다.
(2) 재사용 가능한 템플릿
Pug는 block, include, mixin 등을 이용해서 반복적으로 사용되는 코드를 재사용할 수 있습니다. 이를 통해 중복 코드를 줄이고 유지보수를 효율적으로 할 수 있습니다.
(3) 동적 콘텐츠 생성
Pug는 JavaScript와 쉽게 통합되어 동적인 데이터를 기반으로 HTML을 생성할 수 있습니다.
ul
each item in ['사과', '바나나', '포도']
li= item
이렇게 쓴 것은,
<ul>
<li>사과</li>
<li>바나나</li>
<li>포도</li>
</ul>
이것과 동일합니다.
3. Pug 주요 기능
1)조건문
if user
p 환영합니다, #{user}님!
else
p 로그인해주세요.
위와 같이 if 조건문 작성이 가능합니다.
(2) 반복문
ul
each item in items
li= item
이렇게 반복문도 가능하구요
(3) 속성 지정
a(href="https://example.com" target="_blank") 링크 텍스트
이렇게 attribute 지정도 가능합니다.
4. Pug 설치 및 사용 방법
1)설치
Pug는 Node.js 환경에서 작동하기 때문에, npm install pug 명령어로 간단히 설치가 가능합니다.
2)사용
우선, template.pug 파일을 생성해봅시다.
html
head
title 사용자 페이지
body
if user
h1 안녕하세요, #{user}님!
else
h1 안녕하세요, 방문자님!
p Pug로 동적 HTML을 생성하는 예제입니다.
그 다음, server.js 파일을 다음과 같이 만들어줍시다.
const pug = require('pug');
// Pug 템플릿 컴파일
const compiledFunction = pug.compileFile('template.pug');
// HTML 생성
console.log(compiledFunction({ user: '홍길동' }));
그리고 node server.js 명령어를 이용해 server.js 파일을 실행하면
우리가 원하는 대로 출력이 되는 걸 확인할 수 있습니다.
5. 백엔드 작업에서 Pug를 주로 어디다 씀?
1)서버 사이드 렌더링(SSR)
Pug는 Node.js 기반의 서버 환경에서 클라이언트에게 전달할 동적 서버 사이드 렌더링 작업에 사용될 수 있습니다.
참고로, 서버사이드 렌더링은 서버에서 완전한 HTML 페이지를 생성하여 클라이언트로 보내는 방식입니다.
먼저 ssr.pug파일을 만들어줍시다.
html
head
title #{title}
body
h1 #{title}
p #{description}
p 페이지 생성 시각: #{timestamp.toLocaleString()}
이제 server.js 파일을 만들어줍시다.
const express = require("express");
const pug = require("pug");
const app = express();
// Pug 템플릿 경로 설정
app.set("view engine", "pug");
app.set("views", "./");
// 라우트 설정
app.get("/", (req, res) => {
const pageData = {
title: "SSR 페이지",
description: "이 페이지는 서버사이드 렌더링으로 생성되었습니다.",
timestamp: new Date(),
};
res.render("ssr", pageData);
});
// 서버 실행
const PORT = 8000;
app.listen(PORT, () => {
console.log(`서버가 실행 중입니다: http://localhost:${PORT}`);
});
res.render('index', { title: '홈페이지', message: 'Pug로 동적 HTML 만들기!' }); 코드를 실행하게 되면 index.pug를 읽고 전달된 데이터를 템플릿에 삽입하여 완성된 HTML을 생성한 뒤, 클라이언트에게 반환하게 됩니다.
서버 측에서 입력받은 데이터를 바탕으로 html을 생성해서 클라이언트에게 전달해주는 것이니 서버사이드 렌더링이겠죠?
동적 콘텐츠를 포함한 HTML이 이미 생성된 상태로 전달되기 때문에, 클라이언트는 렌더링 로직 없이 페이지를 바로 표시할 수 있습니다.
결과물은 다음과 같을 겁니다.
이렇게 뜨게 됩니다. 만약 파일을 찾을 수 없다고 뜨거나 하면 파일들의 경로를 한 번 확인해보세요. 여기서는 pug 파일의 경로가 "./", 즉 프로젝트 폴더입니다.
2)동적 콘텐츠 처리
또한, PUG는 서버에서 데이터를 받아 이를 기반으로 HTML을 구성해야 할 때 유용하게 쓰일 수 있습니다.
먼저, user.pug를 만들어 줍시다.
html
head
title 사용자 목록
body
h1 사용자 목록
ul
each user in users
li #{user.name} (#{user.age}세)
다음으로, server.js를 만들어줍시다.
const express = require("express");
const pug = require("pug");
const app = express();
// Pug 템플릿 경로 설정
app.set("view engine", "pug");
app.set("views", "./");
// 데이터 예제
const users = [
{ name: "홍길동", age: 30 },
{ name: "김철수", age: 25 },
{ name: "이영희", age: 35 },
];
// 라우트 설정
app.get("/", (req, res) => {
res.render("users", { users });
});
// 서버 실행
const PORT = 8000;
app.listen(PORT, () => {
console.log(`서버가 실행 중입니다: http://localhost:${PORT}`);
});
이제 server.js로 서버를 띄우고 8000번 포트에 들어가게 되면
이렇게 뜨게 됩니다. 만약 파일을 찾을 수 없다고 뜨거나 하면 파일들의 경로를 한 번 확인해보세요. 여기서는 pug 파일의 경로가 "./", 즉 프로젝트 폴더입니다.
3)서버 사이드 렌더링하고 동적 컨텐츠 처리 똑같은 거 아님?
두 작업 모두 템플릿에 데이터를 주입하여 HTML을 생성하는 방식이기 때문에 코드 구조가 비슷해보이죠. 또한, 뭔가의 입력값을 바탕으로 가변적으로 서버에서 처리해서 클라이언트에게 보여주는 느낌도 같죠.
굳이 구분해야 하나 싶긴 하지만, 그냥 동적 컨텐츠 처리는 서버에서 데이터를 가져와 UI에 유동적으로 반영시키는 것에 초점이 맞춰져있고,서버 사이드 렌더링은 클라이언트가 추가 렌더링 없이 바로 볼 수 있는 완전한 HTML을 제공하는 것에 초점이 맞춰져있다고 생각하면 편할 것 같습니다.
6. 실제론 어떻게 씀?
여태까지 다뤘던 예시들은 서버에서 사전에 정의된 값을 그냥 동적으로 보여주기만 했는데요.
보통은 클라이언트가 입력한 값이나 요청에 따라 동적인 화면을 보여주겠죠?
그 예시도 하나 만들어보겠습니다.
우선 server.js입니다.
const express = require("express");
const pug = require("pug");
const bodyParser = require("body-parser");
const app = express();
// Pug 템플릿 설정
app.set("view engine", "pug");
app.set("views", "./");
// body-parser 미들웨어 설정 (POST 데이터 파싱)
app.use(bodyParser.urlencoded({ extended: true }));
// GET: 폼 페이지 렌더링
app.get("/", (req, res) => {
res.render("form");
});
// POST: 클라이언트 입력 처리
app.post("/submit", (req, res) => {
const { name, message } = req.body;
res.render("response", { name, message });
});
// 서버 실행
const PORT = 3000;
app.listen(PORT, () => {
console.log(`서버가 실행 중입니다: http://localhost:${PORT}`);
});
form.pug 입니다.
html
head
title 입력 폼
body
h1 사용자 입력 폼
form(action="/submit" method="post")
label(for="name") 이름:
input(type="text" id="name" name="name" required)
br
label(for="message") 메시지:
textarea(id="message" name="message" required)
br
button(type="submit") 제출하기
입력받은 값을 토대로 렌더링해주는 response.pug입니다.
html
head
title 입력 결과
body
h1 입력 결과
p 이름: #{name}
p 메시지: #{message}
a(href="/") 다시 입력하기
이렇게 작업을 해주면, home 경로에서는 form.pug에서 정의한 대로 아래와 같은 폼이 나옵니다.
또한, 값을 입력해서 제출하게 되면 response.pug 정의한 대로 입력 결과를 보여주는 화면이 렌더링되게 됩니다.
이상입니다.
읽어주셔서 감사합니다.
'CS' 카테고리의 다른 글
웹소켓 구현해보기 1편 - 웹소켓의 정의와 웹소켓 서버 생성 (Web Socket with Node.js) (0) | 2025.01.25 |
---|---|
[Node.js] Express.static 메서드 사용해보기 (0) | 2025.01.21 |
포트(Port)는 무엇일까? (2) | 2025.01.18 |
GET 방식에서 URL에 데이터를 전달하는 두 가지 방법 : params, query (0) | 2025.01.18 |
GET 방식과 POST 방식 차이(feat. REST) (0) | 2025.01.18 |