Java : JSP 코드 블록 종류와 사용 예시

NuyHes·2025년 8월 19일
0

[Study]

목록 보기
67/71
post-thumbnail

🕵️ JSP 와 컴파일 코드

📄example.jsp

// example.jsp
<html lang="ko">  
    <head>  
        <meta charset="UTF-8">  
        <title>JSP - Hello World</title>  
    </head>  
    <body>  
        <h1>Hello</h1>  
    </body>  
</html>

📄example.jsp 의 서블릿 컴파일 코드

public final class calculator_jsp extends org.apache.jasper.runtime.HttpJspBase
    implements org.apache.jasper.runtime.JspSourceDependent,
                 org.apache.jasper.runtime.JspSourceImports {

	// 멤버함수 , 멤버변수

	public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {
	
		// 지역변수 , 알고리즘

    }
}

_jspService()

이 메서드가 JSP한 요청의 실제 처리를 한다. 원래 service()를 오버라이드하는 서블릿과 달리 Jasper_jspService로 생성하고 컨테이너가 호출한다.


예제

📄example.jsp

// example.jsp

1️⃣ 환영합니다.

<html lang="ko">  
    <head>  
        <meta charset="UTF-8">  
        <title>JSP - Hello World</title>  
    </head>  
    <body>  
        <h1>Hello</h1>  
    </body>  
</html>

가령 상단에 1️⃣번 처럼 환영합니다.를 쓰게 된다면 서블릿 컴파일은 아래와 같이 출력을 하게된다.

public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {
	
		1️⃣out.write("환영합니다.");

    }

하지만 실행되어야할 코드를 넣을 땐 아래와 같이 코드 블록을 사용한다.

📄example.jsp

// example.jsp
 <%
    1️⃣ y = x + 3
   %>
<html lang="ko">  
    <head>  
        <meta charset="UTF-8">  
        <title>JSP - Hello World</title>  
    </head>  
    <body>  
        <h1>Hello</h1>  
    </body>  
</html>

📄example.jsp 의 서블릿 컴파일 코드

public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response)
      throws java.io.IOException, javax.servlet.ServletException {
	
		1️⃣ y = x + 3

    }

<% %> 를 사용하게 되면 _jspService메서드에 선언이 된다.


🕵️ 함수를 선언하고 싶으면

아래와 같이 JSP파일에서 함수를 선언하고 싶을 때는 이렇게 사용을 하면 에러가 발생한다.

❌
<% 
	public int sum (int a, int b) {
		return a + b;
	}
%>

👌
<%!
	public int sum (int a, int b) {
		return a + b;
	}
%>

<% %> 를 사용하게 되면 _jspService메서드에 선언이 되기 때문이다. 메서드 내부에 또다른 메서드가 정의가 되는 것이 되므로 컴파일 에러가 발생한다. 그래서 클래스 내부에 메서드가 정의되어야 함으로 <%! %> 를 사용한다.


🕵️ JSP 문법 / 스타일과 사용 예시

📌 1) 정적 템플릿 / HTML

  • 컴파일 시 : _jspService 내부에 out.write("...")
  • 런타임 시 : _jspService(...) 안에서 그대로 출력됨

예시

용도: 고정 레이아웃/마크업, 변하지 않는 안내문

<!-- header.jsp -->
<header class="gnb">
  <a href="/">Home</a>
  <nav> ... </nav>
</header>

팁: 정적 레이아웃은 JSP 인클루드(정적/동적)로 재사용하면 유지보수 용이


📌 2) 스크립틀릿 <% ... %>

  • 컴파일 시 : _jspService 메서드 몸통에 그대로 삽입
  • 런타임 시 : _jspService(...) 실행 시 자바 코드 수행
  • ⚠️ 메서드/필드 선언 불가 → 선언부 <%! ... %> 사용해야 함

예시

용도: 임시 디버깅/레거시 코드에서 빠른 분기

<%-- 가급적 JSTL/EL로 대체 --%>
<%
  boolean isAdmin = "admin".equals(session.getAttribute("role"));
  if (!isAdmin) { response.sendRedirect("/403.jsp"); return; }
%>

팁: 실무에선 JSTL/EL + 컨트롤러에서 데이터 준비로 대체하는 게 표준


📌 3) 표현식 <%= ... %>

  • 컴파일 시 : _jspService 안의
    out.write(String.valueOf(...))
  • 런타임 시 : 값이 계산된 뒤 즉시 출력
  • 예제: <%= 1 + 2 %> <!-- 출력: 3 -->

예시

용도: 간단 값 출력(로그인 사용자명 등)

<p>안녕하세요, <strong><%= request.getAttribute("userName") %></strong> 님!</p>

팁: 표현식도 지양하고 ${userName} EL을 쓰는 게 더 안전/일관


📌 4) EL (Expression Language) ${ ... }

  • 컴파일 시 :
    PageContextImpl.proprietaryEvaluate(...)
    또는 ExpressionFactory 호출
  • 런타임 시 : _jspService(...) 중 EL 평가 후 출력
  • 특징 : page/request/session/application 스코프에서 속성 탐색

예시

용도: 모델 데이터 출력/간단 계산/널 안전 접근

<p>안녕하세요, <strong>${user.name}</strong> 님!</p>
<p>장바구니: ${cart.totalCount}개 / 합계: ${cart.totalPrice}원</p>
<p>기본값: ${empty user.nickname ? user.name : user.nickname}</p>

팁: EL은 속성 스코프(page/request/session/application)에 있는 값만 본다.
컨트롤러/서블릿에서 request.setAttribute("user", userDto) 식으로 전달


📌 5) 선언부 <%! ... %> (필드/메서드 선언)

  • 컴파일 시 : 클래스 레벨에 필드/메서드 정의
    jspInit() / jspDestroy() → 각각 _jspInit() / _jspDestroy()
  • 런타임 시 :
    • 로딩 시 1회 : _jspInit()
    • 언로드 시 1회 : _jspDestroy()

예시

용도: (지양) 페이지 전역 유틸/상수/초기화 로직

<%!
  private static final String VERSION = "v1.2.3";
  public void jspInit() { getServletContext().log("calculator.jsp init"); }
  public void jspDestroy() { getServletContext().log("calculator.jsp destroy"); }
%>
<footer>build: <%= VERSION %></footer>

팁: 전역/상태는 서블릿/필터/리스너/스프링 빈으로 옮기는 게 베스트


📌 6) page 디렉티브 <%@ page ... %>

  • 컴파일 시 : import, buffering, session, errorPage, contentType 등 메타 구성
  • 런타임 시 : _jspService 시작부에서 response.setContentType(...) 등 설정 적용

예시

용도: 인코딩/버퍼/임포트/에러 페이지 등 JSP 동작 설정

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"
         buffer="8kb" autoFlush="true" isELIgnored="false" %>
<%@ page import="java.time.LocalDateTime" %>

팁: 한글 깨짐 방지: contentType + pageEncoding 둘 다 UTF-8 명시


📌 7) include 디렉티브 <%@ include file="..." %> (정적 include)

  • 컴파일 시 : 번역 시점에 파일 합쳐짐 → 하나의 서블릿으로 컴파일
  • 런타임 시 : 별도 메서드 호출 없음 (정적 결합)

예시

용도: 빌드 타임 결합(공통 헤더/푸터/메뉴) – 한 서블릿으로 컴파일

<%@ include file="/WEB-INF/views/common/header.jsp" %>
<main>...</main>
<%@ include file="/WEB-INF/views/common/footer.jsp" %>

팁: 정적 include는 변수 공유가 쉽고 성능도 좋음. 단 파일 간 의존 주의


📌 8) JSP 액션: <jsp:include page="..."> (동적 include)

  • 컴파일 시 :
    JspRuntimeLibrary.include(...) 또는 RequestDispatcher.include(...) 호출 생성
  • 런타임 시 : 실행 시 다른 리소스의 출력 포함

예시

용도: 런타임에 다른 리소스 출력 포함(동적 데이터 포함)

<jsp:include page="/banner.jsp">
  <jsp:param name="slot" value="HOME_TOP"/>
</jsp:include>

팁: 동적 include는 각 JSP가 독립적으로 실행되어 유지보수에 유리


📌 9) JSP 액션: <jsp:forward page="...">

  • 컴파일 시 :
    JspRuntimeLibrary.forward(...) 호출 후 SkipPageException 처리
  • 런타임 시 : forward 호출 후 현재 JSP의 나머지 출력은 스킵

예시

용도: 조건부로 다른 화면으로 넘기기(남은 출력 스킵)

<c:if test="${empty sessionScope.user}">
  <jsp:forward page="/login.jsp"/>
</c:if>

팁: 컨트롤러(서블릿/스프링)에서 forward/redirect를 결정하는 구조가 더 깔끔


📌 10) JSP 액션: useBean / setProperty / getProperty

  • 컴파일 시 :
    pageContext.findAttribute(...) → 없으면 생성 → 세터 호출 코드 생성
  • 런타임 시 : 빈 생성 및 속성 설정 코드 실행

예시

용도: (레거시) JSP에서 자바빈을 생성/프로퍼티 채우기/출력

<jsp:useBean id="form" class="com.example.Form" scope="request"/>
<jsp:setProperty name="form" property="*" /> <%-- 파라미터 이름과 매핑 --%>
이름: <jsp:getProperty name="form" property="name"/>

팁: 현대 실무는 컨트롤러가 DTO를 채워 request.setAttribute("form", dto) 로 전달


📌 11) 커스텀 태그 (JSTL <c:...>, <fmt:...> 등)

  • 컴파일 시 : 태그 핸들러 객체 생성 → setPageContext / 속성 setter → doStartTag() / doEndTag() 호출 코드 생성
  • 런타임 시 : 태그 핸들러 메서드 실행으로 로직 수행

예시

용도: 조건/반복/국제화/포맷팅/URL 빌드 등 뷰 로직

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt"  prefix="fmt" %>

<c:if test="${not empty products}">
  <ul>
    <c:forEach var="p" items="${products}">
      <li>${p.name} - <fmt:formatNumber value="${p.price}" type="currency"/></li>
    </c:forEach>
  </ul>
</c:if>

팁: 조건/반복은 JSTL로, 단순 출력/연산은 EL로. 스크립틀릿은 지양


📌 12) JSP 주석 <%-- ... --%>

  • 번역 시 : 아예 제거됨
  • 런타임 시 : 실행/출력 없음 (클라이언트에 노출되지 않음)

예시

용도: 운영에 노출되면 안 되는 내부 메모/비밀 값

<%-- TODO: 결제 수수료 정책 변경(9/1) --%>

팁: 클라이언트에 절대 노출 안 됨. 반면 HTML 주석은 노출됨!


📌 13) HTML 주석 <!-- ... -->

  • 컴파일 시 : out.write("<!-- ... -->")
  • 런타임 시 : 그대로 클라이언트에 출력됨 (소스 보기에서 보임)

예시

용도: 프론트 협업용 가이드 주석(노출 허용 가능 내용만)

<!-- 여기는 런딩 상단 배너 영역 -->

팁: 브라우저 “보기-소스”에 그대로 보임 민감한 내용 금지


⚙️ 실행 흐름 요약

  1. 서블릿 로딩 시 (1회)

    • 선언부의 jspInit()_jspInit() 실행
  2. 매 요청마다

    • _jspService(request, response) 실행
    • 암묵 객체 준비 (request, response, session, application, out 등)
    • page 디렉티브 설정 적용
    • 스크립틀릿 / 표현식 / EL / 액션 / 태그 순서대로 실행
  3. 서블릿 언로드 시 (1회)

    • 선언부의 jspDestroy()_jspDestroy()

0개의 댓글