4-3. 템플릿 엔진(JSP) (3세대)

박은서's avatar
Jan 28, 2026
4-3. 템플릿 엔진(JSP) (3세대)

1. 템플릿 엔진(JSP) (3세대)

1️⃣ 3세대 등장 배경

1) 1세대: 서블릿이 HTML을 직접 생성

out.println("<html>"); out.println("<body>"); out.println("<h1>Hello</h1>");
문제
  • HTML 구조 파악 불가
  • 디자이너랑 협업 불가능
  • 수정 = 자바 코드 수정
  • 가독성 💥 유지보수 💥
➡️ 그래서 나온 생각이 “HTML은 HTML답게 두자”

2) 2세대: HTML에 자바 코드를 넣자 (JSP 초창기)

<html> <body> <% for(int i=0;i<10;i++){ %> <p><%= i %></p> <% } %> </body> </html>
장점
  • HTML 구조가 눈에 보임
  • 화면 개발이 쉬워짐
하지만…
  • JSP 안에 로직, 조건문, 반복문 난무
  • 비즈니스 로직 + 화면 로직 뒤섞임
  • 디자이너가 보면 공포 영화
➡️ JSP가 컴퍼트(복잡)해짐

3) 문제의 핵심

“컴퍼트가 돼서 서블릿 되는 것”
⬇️
  • JSP가 원래는 “뷰(View)” 역할인데
  • 로직이 점점 많아지면서
  • 사실상 서블릿처럼 동작
  • MVC에서 View가 Controller 역할까지 침범
⚠️ 기술적으로는
JSP는 컴파일되면 실제로 서블릿으로 변환됨

4) 3세대의 등장

3세대의 철학
❌ “HTML 안에 자바 코드 넣지 말자”
✅ “HTML + 최소한의 표현식만 허용하자”
대표 예시
  • JSP + JSTL/EL
  • Thymeleaf
  • Freemarker
  • Velocity
<tr th:each="user : ${users}"> <td th:text="${user.name}"></td> </tr>
특징
  • 자바 코드 ❌
  • if / loop 정도만 허용
  • 비즈니스 로직은 Controller/Service로 이동
  • View는 진짜 View만 담당

2️⃣ 템플릿 엔진

1) 템플릿 엔진이란?

데이터를 HTML 템플릿에 끼워 넣어서 최종 HTML을 만들어주는 도구

2) 템플릿 엔진의 동작 원리

① 서버 측에서 자바 코드를 해석해서 브라우저로 전송
  • JSP / 템플릿 엔진은 서버 사이드 렌더링(SSR)
  • 브라우저는 HTML만 받음
  • 자바 코드는 서버에서 이미 실행됨
브라우저는 자바/JSP/Thymeleaf를 절대 해석하지 않는다
② 브라우저에서 jsp파일 요청하면 이 파일은 서블릿 파일로 바뀜
JSP의 내부 동작 순서:
.jsp 요청 → JSP 엔진이 .java(Servlet) 파일 생성 → 컴파일 → .class → 실행
“JSP는 실행 시 서블릿으로 변환된다”
③ jsp파일은 누구도 해석하지 못하는 파일
정확히 말하면
  • 브라우저 ❌
  • 클라이언트 ❌
  • 서버의 JSP 엔진만 해석 가능
JSP는 서버 전용 템플릿 파일이며 클라이언트는 접근하거나 해석할 수 없다

3️⃣ JSP와 템플릿 엔진

1) JSP (구식 스타일)

  • 템플릿 엔진은 맞음
<% if(user.isAdmin()){ %> <p>관리자</p> <% } %>
  • 자바 코드 직접 사용 가능
  • View에 로직 침투 쉬움
  • MVC 무너지기 쉬움

2) 3세대 템플릿 엔진 (Thymeleaf 등)

<p th:if="${user.admin}">관리자</p>
  • 자바 코드 ❌
  • 표현식만 허용
  • 비즈니스 로직은 Controller/Service로 제한
“View는 View답게” 만들려고 설계됨

3) JSP와 3세대 템플릿 엔진

구분
JSP
3세대 템플릿 엔진
자바 코드
사용 가능
❌ 사용 불가
로직 위치
View에 섞이기 쉬움
Controller로 강제
MVC 유지
어려움
쉬움
디자이너 협업
어려움
쉬움
현대 프레임워크 궁합
나쁨
좋음

4) 정리

  • JSP
    • → “옛날 템플릿 방식”
  • 템플릿 엔진
    • → “Thymeleaf / Freemarker 같은 3세대 뷰 기술”
개념적으로는 포함 관계지만, 실무적으로는 구분해서 말함

2. 실습

1️⃣ 실습 시작 전 설정

1) 라이브러리 추가

// JSP 엔진(톰캣 Jasper) implementation 'org.apache.tomcat.embed:tomcat-embed-jasper' // JSTL (EL, core 태그) implementation 'jakarta.servlet.jsp.jstl:jakarta.servlet.jsp.jstl-api' implementation 'org.glassfish.web:jakarta.servlet.jsp.jstl'
notion image

2) 폴더 설정

/resources/META-INF/resources
META-INF 폴더 추가
resources 폴더 추가
notion image
실행하면 서블릿파일로 자동 변환됨

2️⃣ 3세대 파일 만들기

1) index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <h1>index 페이지</h1> <% int num = 10; %> <h3>값 : <%=num%></h3> </body> </html>

2) V3Application

package com.example.v3; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class V3Application { public static void main(String[] args) { SpringApplication.run(V3Application.class, args); } }

3) 브라우저

notion image
브라우저가 인덱스.jsp의 전체 내용을 담은 것이 아님(=버퍼안에 내용이 담기진 않았음.)
자바코드(서버측)가 해석을 도와주었기 때문에 브라우저에 띄울 수 있는 것임.(컴파일 ⭕)
notion image
톰캣이 자바코드를 해석하여 브라우저에 순수 html을 띄워준 것임.

4) 최종코드

템플릿 엔진(JSP) : jsp코드가 아래와 같이 servelt 으로 변환 (자동)
package com.example.v3; import java.io.IOException; import java.io.PrintWriter; import jakarta.servlet.ServletException; import jakarta.servlet.annotation.WebServlet; import jakarta.servlet.http.HttpServlet; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @WebServlet("/index.jsp") public class MyServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { int num = 10; String html = """ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> </head> <body> <h1>index 페이지</h1> <h3>값 : <%=num%></h3> </body> </html> """.replace("<%=num%>", num + ""); resp.setContentType("text/html; charset=utf-8"); PrintWriter pw = resp.getWriter(); pw.println(html); } }
notion image
옛날문법 이제 안씀
추상적인 틀만 이해하세요
notion image

3. 템플릿 엔진의 단점

1) UI(html)와 비즈니스로직(자바) 코드 혼재 → 유지보수 어려움

이건 “JSP 스크립틀릿 기반 구조”의 핵심 문제
예:
<% if(user.isAdmin()){ service.doSomething(); } %>
문제점:
  • View에 비즈니스 로직 침투
  • MVC 구조 붕괴
  • 디자이너/프론트엔드 접근 불가
  • 테스트 어려움
📌 그래서 나온 결론:
View에는 로직을 최소화해야 한다
⚠️ 중요한 포인트
👉 이 문제를 해결하려고 등장한 게 “3세대 템플릿 엔진”
즉,
  • ❌ 3세대의 단점
  • ⭕ 3세대의 등장 배경

2) 단일진입점 없음

이것도 JSP 직접 호출 구조의 문제
JSP를 이렇게 쓰면:
/login.jsp /list.jsp /admin.jsp
문제:
  • URL마다 JSP 직접 접근 가능
  • 인증/권한 체크 중복
  • 공통 로직 분산
📌 이 문제 때문에 등장한 개념:
  • Front Controller
  • 예: DispatcherServlet

3) 필기

notion image
Share article