일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- git
- @media
- 코딩테스트
- node.js
- node
- 그럼에도 불구하고
- CSS
- HTML
- react-router-dom
- media query
- react
- 자바
- redux
- 반응형 페이지
- 프론트엔드
- webpack
- github
- cleancode
- 코드업
- TypeScript
- coding
- frontend
- max-width
- JavaScript
- 변수
- JS
- java
- 자바문제풀이
- 그럼에도불구하고
- Servlet
- Today
- Total
그럼에도 불구하고
[EJS] EJS에 대해 알아보자 본문
EJS에 대해 알아보자
[ 템플릿 엔진 ]
웹 페이지 구성 시 가장 기본적으로 쓰이는 마크업 언어인 HTML은 정적인 언어이다.
정적이기 때문에 주어진 기능만 사용할 수 있으며, 직접 기능을 추가할 수 없다. ( 자바스크립트를 사용하면 가능하다.)
템플릿 엔진은 자바스크립트를 사용하여 HTML을 렌더링 할 수 있게 해 준다. 따라서 기존 HTML과 문법이 다른 부분이 있고, 자바스크립트 문법이 들어가기도 한다. ( 놀랍다. )
템플릿 엔진에는 대표적으로 퍼그 (Pug), EJS, Handlebars 등이 있다.
https://despiteallthat.tistory.com/152
[ EJS 설치 ]
npm install ejs --save
EJS는 PUG와 같이 즉시 지원이 되는 템플릿 엔진이기 때문에 Handlebars처럼 엔진을 등록할 필요가 없으며,
app.js에서 view engine을 'ejs'로 선언해 주면 된다.
view engine에 대한 자세한 설명은 아래의 링크를 참고하자 :)
https://despiteallthat.tistory.com/152
[ EJS 사용 ]
EJS는 Pug와 달리 HTML 양식을 그대로 사용할 수 있다.
또한, EJS는 Pug와 달리 extends와 같은 레이아웃을 지원하지는 않지만, 일부 구축 블록들을 재활용할 수 있는 include라는 솔루션을 갖고 있다.
기존 html 파일을 EJS로 변환하는 과정을 보자
shop.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | <!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"> <title>Shop</title> <link rel="stylesheet" href="/css/main.css"> </head> <body> <header class="main-header"> <nav class="main-header__nav"> <ul class="main-header__item-list"> <li class="main-header__item"><a class="active" href="/">Shop</a></li> <li class="main-header__item"><a href="/admin/add-product">Add Product</a></li> </ul> </nav> </header> <main> <h1>My Products</h1> <p>List of all the products...</p> </main> </body> </html> | cs |
add-product.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <!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"> <title>Add Product</title> <link rel="stylesheet" href="/css/product.css"> <link rel="stylesheet" href="/css/forms.css"> <link rel="stylesheet" href="/css/main.css"> </head> <body> <header class="main-header"> <nav class="main-header__nav"> <ul class="main-header__item-list"> <li class="main-header__item"><a href="/">Shop</a></li> <li class="main-header__item"><a class="active" href="/admin/add-product">Add Product</a></li> </ul> </nav> </header> <main> <form class="product-form" action="/admin/add-product" method="POST"> <div class="form-control"> <label for="title">Title</label> <input type="text" name="title" id="title"> </div> <button class="btn" type="submit">Add Product</button> </form> </main> </body> </html> | cs |
404.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <!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"> <title>404 Error</title> <link rel="stylesheet" href="/css/main.css"> </head> <body> <header class="main-header"> <nav class="main-header__nav"> <ul class="main-header__item-list"> <li class="main-header__item"><a href="/">Shop</as=></li> <li class="main-header__item"><a href="/admin/add-product">Add Product</a></li> </ul> </nav> </header> <h1>Page Not Found</h1> </body> </html> | cs |
위 3개의 html 파일에서 공통된 부분을 분리해 보자
head.ejs
1 2 3 4 5 6 7 8 | <!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"> <title><%= pageTitle %></title> <link rel="stylesheet" href="/css/main.css"> | cs |
head.ejs에서는 동적 랜더링을 위해 title를 <%= pageTitle %>과 같이 설정해 줬다.
이는 각각의 js 파일에서 랜더링 할 때 pageTitle를 키로 설정하고 내가 설정하고 싶은 title를 값으로 설정해 주면 된다.
shop.js
admin.js
404.ejs
navigation.ejs
1 2 3 4 5 6 7 8 | <header class="main-header"> <nav class="main-header__nav"> <ul class="main-header__item-list"> <li class="main-header__item"><a href="/" class="<%= path === '/' ? 'active' : '' %>">Shop</a></li> <li class="main-header__item"><a href="/admin/add-product" class="<%= path === '/admin/add-product' ? 'active' : '' %>">Add Product</a></li> </ul> </nav> </header> | cs |
end.ejs
1 2 3 | </body> </html> | cs |
분리한 블록들은 내가 사용할 ejs 파일에서 include를 통해 사용할 수 있다.
<%- include('includes/head.ejs') %>
<%- include('includes/navigation.ejs') %>
<%- include('includes/end.ejs')%>
shop.ejs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <%- include('includes/head.ejs') %> <link rel="stylesheet", href="/css/product.css"> </head> <body> <%- include('includes/navigation.ejs') %> <main> <% if(prods.length > 0) { %> <div class="grid"> <% for( let product of prods) { %> <article class="card.product-item"> <header class="card__header"> <h1 class="product__title"><%= product.title %></h1> </header> <div class="card__image"> <img src="data:image/jpeg;base64,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", alt="A Book"> </div> <div class="card__content"> <h2 class="product__price">$19.99</h2> <p class="product__description">A very interesting book about so many even more interesting things!</p> <div class="card__actions"> <button class="btn">Add to Cart</button> </div> </div> </article> <% } %> </div> <% } else { %> <h1> No Product Found!</h1> <% } %> </main> <%- include('includes/end.ejs')%> | cs |
add-product.ejs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <%- include('includes/head.ejs') %> <link rel="stylesheet" href="/css/main.css"> <link rel="stylesheet", href="/css/product.css"> <link rel="stylesheet" href="/css/forms.css"> </head> <body> <%- include('includes/navigation.ejs') %> <main> <form class="product-form" action="/admin/add-product" method="POST"> <div class="form-control"> <label for="title">Title</label> <input type="text" name="title" id="title"> </div> <button class="btn" type="submit">Add Product</button> </form> </main> <%- include('includes/end.ejs') %> | cs |
404.ejs
1 2 3 4 5 6 | <%- include('includes/head.ejs') %> </head> <body> <%- include('includes/navigation.ejs') %> <h1>Page Not Found</h1> <%- include('includes/end.ejs') %> | cs |
'Node.js > Template engines' 카테고리의 다른 글
[Png] Pug layout 만들기 (0) | 2023.02.09 |
---|---|
[Png] 동적 콘텐츠 출력 (0) | 2023.02.08 |
[Png] Pug에 대해 알아보자 (0) | 2023.02.08 |