Post

SSR과 템플릿 엔진 선택 기준

SSR의 가치, 템플릿 엔진 비교, XSS 안전한 데이터 주입 원칙을 다룬다

SSR과 템플릿 엔진 선택 기준

결론 요약

  • SSR(Server-Side Rendering)은 “과거 기술”이 아니라 초기 응답·SEO·폼 UX를 안정적으로 해결하는 설계 선택지다.
  • 템플릿 엔진은 HTML 생성 도구가 아니라 반복·조건·레이아웃을 서버에서 관리하기 위한 제어 장치다.
  • Pug/EJS/Handlebars의 차이는 문법 취향이 아니라 디버깅·협업·유지보수 비용에서 갈린다.
  • 데이터 주입은 편의보다 XSS 최소화 규칙을 먼저 잡아야 한다.
  • 오늘날 SSR은 관리자/백오피스/콘텐츠 중심 페이지에서 강하고, 고상호작용 SPA에는 부적합하다.

서버 사이드 렌더링(SSR)과 템플릿 엔진 선택 기준

1️⃣ 정의: SSR이란 무엇인가 (Client Rendering과 비교)

SSR(Server-Side Rendering)

  • 서버가 HTML을 완성해서 클라이언트에 전달
  • 브라우저는 받은 HTML을 즉시 렌더링

CSR(Client-Side Rendering)

  • 서버는 JSON만 제공
  • 브라우저에서 JS가 HTML을 생성
구분SSRCSR
최초 화면빠르고 안정적JS 로딩 후 렌더
SEO유리불리(추가 작업 필요)
폼/에러 UX단순복잡
상호작용제한적강함
복잡도서버 집중프론트 집중

왜 지금도 배우는가 SSR은 “프론트 대체”가 아니라 서버 중심 화면 생성이 더 합리적인 영역을 정확히 커버한다.


2️⃣ 왜 필요한가: 순수 HTML을 관리하면 생기는 문제

순수 HTML 파일로 서버 렌더링을 하면 다음 문제가 즉시 발생한다.

  • 반복되는 마크업(리스트)
  • 조건부 렌더링(로그인/비로그인)
  • 공통 레이아웃(헤더/푸터)
  • 폼 검증 실패 시 입력값 유지

템플릿 엔진은 이 문제를 서버 단에서 선언적으로 해결한다.


3️⃣ 어떻게 동작하는가: 템플릿 엔진의 역할

템플릿 엔진은 다음을 제공한다.

  1. 반복(loop): 리스트 렌더링
  2. 조건(condition): 상태별 출력
  3. 레이아웃(layout): 공통 구조 재사용
  4. partial/include: 컴포넌트화

핵심: HTML을 “문자열”이 아니라 데이터 바인딩 결과물로 취급한다.


4️⃣ toy 예시: 상품 리스트 렌더링

데이터

1
2
3
res.render('products', {
  products: [{ name: 'A' }, { name: 'B' }]
});

EJS 예시

<ul>
  <% products.forEach(p => { %>
    <li><%= p.name %></li>
  <% }) %>
</ul>
  • 반복/출력 분리
  • 데이터 없을 경우 조건 처리 가능

5️⃣ 실무 예시: 폼 검증 오류 + 입력값 유지

문제

  • 검증 실패 시 입력값이 사라짐
  • 사용자 재입력 비용 증가

해결 패턴(SSR)

1
2
3
4
res.render('form', {
  error: '가격은 숫자여야 합니다',
  oldInput: req.body
});
<input name="price" value="<%= oldInput.price %>" />
<% if (error) { %>
  <p><%= error %></p>
<% } %>

이 UX는 CSR에서도 가능하지만, SSR에서는 추가 상태 관리 없이 자연스럽다.


6️⃣ Pug vs EJS vs Handlebars 비교

항목PugEJSHandlebars
문법들여쓰기 기반HTML + JSHTML + 제한된 표현식
생산성빠름(익숙하면)보통보통
디버깅어려움(라인 추적)쉬움중간
협업디자이너 불리유리유리
유지보수취향 의존안정적구조 강제
로직 허용높음높음낮음(의도적)

선택 기준 요약

  • Pug: 소규모/개인 프로젝트, 빠른 작성
  • EJS: 학습·디버깅·유지보수 균형
  • Handlebars: 로직 제한을 통한 구조 강제(팀 협업)

7️⃣ 데이터 주입과 XSS 최소 규칙

핵심 원칙 3가지

  1. 출력 시 escape가 기본인지 확인
  2. 사용자 입력은 그대로 HTML로 넣지 않는다
  3. innerHTML 유사 동작은 피한다
  • EJS: <%= %>는 escape, <%- %>는 raw
  • raw 출력은 신뢰된 데이터에만 사용

과도한 보안 설명은 필요 없다. “raw 출력은 최후의 수단”만 기억하면 된다.


8️⃣ 오늘날 실무 결론: 어디에 쓰면 좋은가 / 나쁜가

쓰면 좋은 경우

  • 관리자/백오피스
  • CMS, 블로그, 문서 페이지
  • 폼 중심 서비스
  • SEO가 중요한 랜딩

쓰면 나쁜 경우

  • 실시간 상호작용이 많은 앱
  • 상태 전이가 복잡한 SPA
  • 클라이언트 로직이 중심인 서비스

SSR은 “대체재”가 아니라 역할이 명확한 선택지다.


재학습 포인트 체크리스트

  • SSR과 CSR의 차이를 UX 기준으로 설명할 수 있다
  • 템플릿 엔진이 해결하는 문제 4가지를 말할 수 있다
  • Pug/EJS/Handlebars의 트레이드오프를 안다
  • 폼 검증 실패 UX를 SSR로 구현할 수 있다
  • raw 출력과 escape 출력의 차이를 이해한다
  • SSR이 적합한 서비스 유형을 구분할 수 있다

This post is licensed under CC BY 4.0 by the author.