1. 템플릿 엔진이란?
HTML에 동적 데이터를 삽입하는 도구. 서버에서 HTML을 받아 HTML로 렌더링
데이터 + 템플릿 = HTML
그런데 여기서 의문점이 하나 생긴다.
서버에서 HTML을 받아 HTML로 또 렌더링을 해?
HTML + HTML = ? 서버에서 내려준다는데 그대로 보여주면 되는 것 아니냐,,
템플릿 엔진의 핵심은 바로 동적 데이터에 있다.
정적 HTML이라면 서버가 파일을 내려주는 그대로 보여줄 수 있지만, 예를 들어 내부의 변수가 렌더링 할 때마다 달라진다면?
고유의 값이 아닌 유동적인 값, 실제 값으로 채우기 위한 과정이라고 할 수 있겠다.
결론 : 서버에서 HTML 배송 -> 프론트가 데이터랑 합쳐서 렌더링!
이라고 생각하면 될 듯 하다.
2. EJS란?
: JS 문법을 그대로 사용하는 템플릿 엔진
<!-- EJS 템플릿 -->
<h1>안녕하세요, <%= name %>님!</h1>
<!-- 데이터 -->
{ name: '홍길동' }
<!-- 결과 HTML -->
<h1>안녕하세요, 홍길동님!</h1>
3. EJS는 현재 어디서 쓸까?

ㅔ.. 지금 회사에서 레거시 코드를 건들면서 새로운 개념을 알게 되어 공부하게 되었다고 생각하면 된다.
회사에서는 주로 Vue를 쓰는데, 레거시 코드를 보니 Vue + EJS를 사용해 배포 중인 프로젝트가 있어 내부를 건드리려고 하면 당연히 배경지식이 필요하다 느꼈다. <%= %>, <% %>, <%- %> 일단 이거보고 필요성을 더 느낌 (어...엉?)
변수 출력(<%= name %>), 조건문(<% if (...) { %>), 반복문(<% for (...) { %>)
이렇게 세 가지만 쓸 줄 알면 실무 EJS의 80%는 읽고 쓸 수 있어요.
Vue의 v-if, v-for랑 역할은 같고 문법만 다르다고 보면 돼요.
라고 클로드가 말해줬다.
a. Express + EJS + Vue
서버(Express)가 EJS로 HTML을 만들고 그 HTML 안에 Vue가 부분적으로 붙어있는 구조다.
Express 서버
↓ EJS로 HTML 생성 (데이터 끼워넣기)
완성된 HTML 클라이언트 전달
↓ HTML 안에 Vue 인스턴스가 있으면
브라우저에서 Vue가 그 부분만 동작
<!-- EJS가 서버에서 데이터 삽입 -->
<div id="app">
<h1><%= title %></h1>
<!-- 이 부분은 Vue가 담당 -->
<vue-component :data="<%= jsonData %>"></vue-component>
</div>
<script src="vue.js"></script>
EJS = 페이지 뼈대 + 초기 데이터, Vue = 동적 인터랙션을 의미한다.
b. Vue
서버는 그냥 빈 HTML이랑 JS 파일만 내려주고, 데이터는 API로 따로 받고, 화면 구성은 전부 브라우저의 Vue가 담당
c. Nuxt
React를 기반으로 만든 SSR 프레임워크 Next.js가 있다면,
Vue에는 SSR 프레임워크 Nuxt.js가 있다.
아직 우리 회사는 레거시 코드가 많아 Express가 직접 SSR 역할을 하고 있고, 그 템플릿 엔진으로 EJS를 쓴 것과 같다.
Next.js = React + SSR/SSG/라우팅/최적화 등 다 묶어놓은 것
Nuxt.js = Vue + SSR/SSG/라우팅/최적화 등 다 묶어놓은 것

저 .. nuxt 쓰고 싶어요
4. 필수 개념
| 태그 | 역할 | 특징 |
|---|---|---|
| <%= %> | 변수 출력 | HTML 이스케이프 O (안전) |
| <% %> | JS 실행 | 화면 출력 없음 |
| <%- %> | 변수 출력 | HTML 이스케이프 X (날것 출력) |
a. 이스케이프란?
저게 뭐지..? 라고 생각해서 좀 찾아봤다 (ㅎㅎ;;)
이건 진짜 생각도 못했었는데, 요즘 프레임워크가 워낙 잘 나오다보니 기본적으로 이스케이프를 자동으로 해준다고 한다.
그래서 개발자가 신경 안써도 알아서 막아준다고.. ㅎ
<% const str = "<strong>굵게</strong>" %>
<%= str %> → <strong>굵게</strong> (태그가 문자로 출력)
<%- str %> → 굵게 (태그가 실제로 적용됨) // 얘가 제일 위험 !
<%- %> 블럭 같은 경우는 내부에 있는 것이 그대로 출력되기 때문에 조심해야 한다.
난 사실 이걸 봐도 와닿지 않아서 ai에게 물어보면서 습득했는데
Vue의 v-html을 쓰지 않는 이유와 같다고 한다.
만약, <%- userInput %>을 그대로 출력했는데, Input에 악의적인 사용자가
<script>document.cookie를 해커서버로 전송</script>
<script>document.cookie를 해커서버로 전송</script>
를 입력하게 되면, 그게 그대로 개발 코드가 아니어도 쏙 들어가서 실행이 된다는 것이다.
그렇게 XSS 공격에 취약하게 된다.
b. <%- %>는 그럼 안쓰나..?
사용자 입력값 → {{ }} 또는 <%= %> (이스케이프 O)
신뢰할 수 있는 내부 데이터 → v-html 또는 <%- %> (이스케이프 X)
1. include (가장 흔함)
<%- include('partials/header') %>
2. 서버/개발자가 직접 만든 HTML 문자열
// 서버에서 개발자가 직접 만든 것
const badge = "<span class='vip'>VIP</span>"
<%- badge %>
사용자 입력이 아니라 개발자가 코드로 만든 거라 신뢰할 수 있어요.
사용자가 노션/워드처럼 생긴 에디터에서 작성
→ 저장될 때 서버에서 HTML 검증/필터링을 거침
→ 그 결과를 출력할 때
이 경우는 사용자 입력이지만 서버에서 한번 걸러진 거라 v-html 사용이라고 정리할 수 있을 것 같다.