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'
2) 폴더 설정
/resources/META-INF/resources
META-INF 폴더 추가
resources 폴더 추가

실행하면 서블릿파일로 자동 변환됨
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) 브라우저

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

톰캣이 자바코드를 해석하여 브라우저에 순수 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);
}
}
옛날문법 이제 안씀
추상적인 틀만 이해하세요

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) 필기

Share article