JiSoo's Devlog

[Node.js] 동적 콘텐츠 작업 및 템플릿 엔진 추가 본문

Backend/Node.js

[Node.js] 동적 콘텐츠 작업 및 템플릿 엔진 추가

지숭숭숭 2024. 10. 28. 15:40

요청 및 사용자 간의 데이터 공유

const products = [];

// admin/add-product => POST
router.post("/add-product", (req, res, next) => {
  products.push({ title: req.body.title });
  res.redirect("/");
});

exports.routes = router;
exports.products = products;

객체나 배열 같은 참조 유형을 내보내기 하면 다른 파일에서 변경하면 저절로 업데이트된다

데이터 공유

 

 

템플릿 엔진

html 페이지에 동적 콘텐츠를 넣기 위해 사용한다

 

· EJS

<p><%= name %></p>

일반 HTML을 사용하고 단순한 JavaScript를 사용할 수 있게 하는 플레이스홀더가 있어 for 루프, if 문 작성 가능

 

· Pug(Jade)

p #{name}

최소 HTML 버전과 맞춤형 템플릿 언어 사용하지만 if문들과 목록 포함 가능

 

· Handlebars

<p>{{ name }}</p>

일반 HTML을 사용하지만 제한된 맞춤형 템플릿 언어도 사용하고 if문이나 목록 등의 공통 요소 포함

 

 

npm install --save ejs pug express-handlebars

npm install 다음에 이름들을 반복 또는 추가해 여러 패키지 한 번에 설치 가능

 

동적 템플릿 렌더링

app.set('view engine', 'pug');

Express 애플리케이션 전체에 어떤 값이든 설정할 수 있고 Express가 이해할 수 없는 키나 구성 항목도 포함한다

view 엔진은 Express에게 동적 view를 어디서 찾을 수 있는지 알리는 기능이 있다

app.set('views', 'views');

view를 다른 폴더에 저장하면 구성 항목을 설정해야 한다

 

.pug 파일에 HTML5 템플릿을 사용하면 pug 구조가 나타난다

일반 HTML 태그는 없지만 pug 템플릿 엔진이 마지막에 코드를 일반 HTML로 컴파일해 준다

doctype html
html(lang="en")
  head
    meta(charset="UTF-8")
    meta(name="viewport", content="width=device-width, initial-scale=1.0")
    title My Shop
    link(rel="stylesheet", href="/css/main.css")
    link(rel="stylesheet", href="/css/product.css")

  body 
    header.main-header
      nav.main-header__nav
        ul.main-header__item-list 
          li.main-header__item
            a.active(href="/") Shop
          li.main-header__item 
            a(href="/admin/add-product") Add Product

 

템플릿 엔진 렌더링 방법

router.get("/", (req, res, next) => {
  res.render('shop');
});

 

 

동적 콘텐츠 출력

router.get("/", (req, res, next) => {
  const products = adminData.products;
  res.render('shop', {prods: products});
});

렌더링 메서드의 두 번째 인수에는 view에 추가되어야 하는 데이터를 넣을 수 있다

자바스크립트 객체 형태로 전달하며 키 이름에 매핑한 뒤 템플릿 내부에서 전달하는 데이터 참조를 위해 사용한다

 

res.render('shop', {prods: products, docTitle: 'Shop'});
title #{docTitle}

docTitle 전달하고 사용 가능

 

 

레이아웃 추가

중복되는 부분이 있을 때 레이아웃 파일을 따로 만들 수 있는데 이 레이아웃은 다른 pug view의 내부로부터 확장할 수 있다

doctype html
html(lang="en")
  head
    meta(charset="UTF-8")
    meta(name="viewport", content="width=device-width, initial-scale=1.0")
    title Page not Found
    link(rel="stylesheet", href="/css/main.css")
    block styles
  body
    header.main-header
      nav.main-header__nav
        ul.main-header__item-list 
          li.main-header__item
            a(href="/") Shop
          li.main-header__item 
            a(href="/admin/add-product") Add Product 
    block content

동적으로 입력 가능한 훅 2개

extends layouts/main-layout.pug 

block content 
  h1 Page not Found!
extends layouts/main-layout.pug 

block styles 
  link(rel="stylesheet", href="/css/forms.css")
  link(rel="stylesheet", href="/css/product.css")

block content
  main
      form.product-form(action="/admin/addproduct", method="POST")
          .form-control
            label(for="title") Title 
            input(type="text", name="title")#title
          button.btn(type="submit") Add Product

 

router.get("/add-product", (req, res, next) => {
  res.render("add-product", { pageTitle: "Add Product", path: 'add-product' });
});

이렇게 path 추가 후 

a(href="/admin/add-product", class=(path === '/admin/add-product' ? 'active' : '')) Add Product

 

 

핸들바 작업

express-handlebars는 Express에 의해 자동으로 설치되는 패키지는 아니라서 직접 알려줘야 한다

const expressHbs = require('express-handlebars');

app.engine('handlebars', expressHbs());
app.set("view engine", "handlebars");

handlebars는 일반 html과 일부 사용자 지정 구문을 사용한다

동적 title을 출력하고 싶으면

<title>{{ pageTitle }}</title>

 

 

핸들바 레이아웃

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>{{ pageTitle }}</title>
    <link rel="stylesheet" href="/css/main.css">
    {{#if formsCSS}}
    <link rel="stylesheet" href="/css/forms.css">
    {{/if}}
    {{#if productCSS}}
    <link rel="stylesheet" href="/css/product.css">
    {{/if}}

  </head>
  <body>
    <header class="main-header">
      <nav class="main-header__nav">
        <ul class="main-header__item-list">
          <li class="main-header__item"><a class="{{#if activeShop }}active{{/if}}" href="/">Shop</a></li>
          <li class="main-header__item">
            <a class="{{#if activeAddProduct }}active{{/if}}" href="/admin/add-product">Add Product</a>
          </li>
        </ul>
      </nav>
    </header>
    {{{ body }}}
  </body>
</html>

 

 

EJS

PUG처럼 즉시 지원이 가능한 템플릿 엔진이라 따로 등록할 필요는 없다

동적 title을 원한다면

<title><%= pageTitle %></title>

 

부분 레이아웃 작업

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title><%= pageTitle %></title>
    <link rel="stylesheet" href="/css/main.css">

↑ head.ejs

<header class="main-header">
  <nav class="main-header__nav">
    <ul class="main-header__item-list">
      <li class="main-header__item">
        <a class="<%= path === '/' ? 'active' : '' %>" href="/"
          >Shop</a
        >
      </li>
      <li class="main-header__item">
        <a class="<%= path === '/admin/add-product' ? 'active' : '' %>" href="/admin/add-product">Add Product</a>
      </li>
    </ul>
  </nav>
</header>

↑ navigation.ejs

 

<%- include('includes/head.ejs') %>
  </head>
  <body>
    <%- include('includes/navigation.ejs') %>
    <h1>Page Not Found!</h1>

<%- include('includes/end.ejs') %>

↑ 404.ejs

 

 

728x90

'Backend > Node.js' 카테고리의 다른 글

[Node.js] 모델 뷰 컨트롤러(MVC)  (1) 2024.11.04
[Node.js] Express.js 작업  (1) 2024.10.22
[Node.js] 개발 워크플로우 및 디버깅  (2) 2024.10.21
[Node.js] 기본 개념  (3) 2024.10.21