-
6. JSP의 기초 다지기JSP 2023. 8. 31. 14:45
6.1 JSP의 개요
61.1 JSP의 특징과 구성요소
JSP의 특징
- HTML에 자바 코드를 직접 사용
- 서블릿 컨테이너에 의해 관리되는 내장객체의
- EL(Expression Language)를 통해 데이터를 표현
JSP의 구성요소
- 지시어
- 액션
- 템플릿 데이터
- 스크립트 요소
- 커스텀 태그와 EL
6.1.2 JSP의 동작과정
출처 : 위키백과 - 'hello.jsp'라는 코드를 작성한다고 가정하고 웹에 배표한다.
- (a) 컨테이너는 해당 jsp 파일의 클래스 변환여부를 확인한다.
- 변환되지 않았다면, 'hello_jsp.java' 파일을 생성하고 .class로 컴파일 한다.
- jspInit() 메서드를 통해 서블릿을 실행한다. jspInit()은 단 한 번만 실행 되어, 서블릿 실행에 필요한 초기 환경을 구축한다.
- _jspService()메서드를 통해 클라이언트 요청을 처리한다.
- 컨테이너 종료 혹은 관리 도구에 의해 서블릿 jspDestroy()를 호출해 jsp가 종료되기 전 후처리를 한 뒤 종료된다.
아래의 jsp코드를 실행하면,
<%@page import="java.time.LocalDateTime"%> <%@ page contentType="text/html; charset=UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Hello</title> </head> <body> <h2>Hello, World...!</h2> <hr /> <h4>현재 날짜와 시간: <%= java.time.LocalDateTime.now() %></h4> </body> </html>
더보기아래의 루트에서 .java로 변환 된다. 매우 길다.
/* * Generated by the Jasper component of Apache Tomcat * Version: Apache Tomcat/9.0.80 * Generated at: 2023-08-30 06:35:59 UTC * Note: The last modified time of this file was set to * the last modified time of the source file after * generation to assist with modification tracking. */ package org.apache.jsp.chap02; import javax.servlet.*; import javax.servlet.http.*; import javax.servlet.jsp.*; import java.time.LocalDateTime; public final class hello_jsp extends org.apache.jasper.runtime.HttpJspBase implements org.apache.jasper.runtime.JspSourceDependent, org.apache.jasper.runtime.JspSourceImports { private static final javax.servlet.jsp.JspFactory _jspxFactory = javax.servlet.jsp.JspFactory.getDefaultFactory(); private static java.util.Map<java.lang.String,java.lang.Long> _jspx_dependants; private static final java.util.Set<java.lang.String> _jspx_imports_packages; private static final java.util.Set<java.lang.String> _jspx_imports_classes; static { _jspx_imports_packages = new java.util.HashSet<>(); _jspx_imports_packages.add("javax.servlet"); _jspx_imports_packages.add("javax.servlet.http"); _jspx_imports_packages.add("javax.servlet.jsp"); _jspx_imports_classes = new java.util.HashSet<>(); _jspx_imports_classes.add("java.time.LocalDateTime"); } private volatile javax.el.ExpressionFactory _el_expressionfactory; private volatile org.apache.tomcat.InstanceManager _jsp_instancemanager; public java.util.Map<java.lang.String,java.lang.Long> getDependants() { return _jspx_dependants; } public java.util.Set<java.lang.String> getPackageImports() { return _jspx_imports_packages; } public java.util.Set<java.lang.String> getClassImports() { return _jspx_imports_classes; } public javax.el.ExpressionFactory _jsp_getExpressionFactory() { if (_el_expressionfactory == null) { synchronized (this) { if (_el_expressionfactory == null) { _el_expressionfactory = _jspxFactory.getJspApplicationContext(getServletConfig().getServletContext()).getExpressionFactory(); } } } return _el_expressionfactory; } public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() { if (_jsp_instancemanager == null) { synchronized (this) { if (_jsp_instancemanager == null) { _jsp_instancemanager = org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getServletConfig()); } } } return _jsp_instancemanager; } public void _jspInit() { } public void _jspDestroy() { } public void _jspService(final javax.servlet.http.HttpServletRequest request, final javax.servlet.http.HttpServletResponse response) throws java.io.IOException, javax.servlet.ServletException { if (!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType())) { final java.lang.String _jspx_method = request.getMethod(); if ("OPTIONS".equals(_jspx_method)) { response.setHeader("Allow","GET, HEAD, POST, OPTIONS"); return; } if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) && !"HEAD".equals(_jspx_method)) { response.setHeader("Allow","GET, HEAD, POST, OPTIONS"); response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSP들은 오직 GET, POST 또는 HEAD 메소드만을 허용합니다. Jasper는 OPTIONS 메소드 또한 허용합니다."); return; } } final javax.servlet.jsp.PageContext pageContext; javax.servlet.http.HttpSession session = null; final javax.servlet.ServletContext application; final javax.servlet.ServletConfig config; javax.servlet.jsp.JspWriter out = null; final java.lang.Object page = this; javax.servlet.jsp.JspWriter _jspx_out = null; javax.servlet.jsp.PageContext _jspx_page_context = null; try { response.setContentType("text/html; charset=UTF-8"); pageContext = _jspxFactory.getPageContext(this, request, response, null, true, 8192, true); _jspx_page_context = pageContext; application = pageContext.getServletContext(); config = pageContext.getServletConfig(); session = pageContext.getSession(); out = pageContext.getOut(); _jspx_out = out; out.write("\n"); out.write("\n"); out.write("<!DOCTYPE html>\n"); out.write("<html>\n"); out.write("<head>\n"); out.write("<meta charset=\"UTF-8\">\n"); out.write("<title>Hello</title>\n"); out.write("</head>\n"); out.write("<body>\n"); out.write("\n"); out.write(" <h2>Hello, World...!</h2>\n"); out.write(" <hr />\n"); out.write("\n"); out.write(" <h4>현재 날짜와 시간: "); out.print( java.time.LocalDateTime.now() ); out.write("</h4>\n"); out.write("</body>\n"); out.write("</html>"); } catch (java.lang.Throwable t) { if (!(t instanceof javax.servlet.jsp.SkipPageException)){ out = _jspx_out; if (out != null && out.getBufferSize() != 0) try { if (response.isCommitted()) { out.flush(); } else { out.clearBuffer(); } } catch (java.io.IOException e) {} if (_jspx_page_context != null) _jspx_page_context.handlePageException(t); else throw new ServletException(t); } } finally { _jspxFactory.releasePageContext(_jspx_page_context); } } }
6.1.3 JSP의 장단점
JSP의 장점
- HTML 파일에 자바 기술을 거의 무한대로 사용할 수 있으며, 비교적 쉽게 프로그래밍할 수 있다.
- JSP 개발에 필요한 확장 태그 구조를 사용할 수 있다.
- 서블릿으로 변환되어 실행되므로 서블릿 기술의 장점을 모두 가진다.
- MVC 패턴, 스프링 프레임워크 등 잘 설계된 구조를 적용 가능. 개발 생산성이 향상되고 성능이 보장된다.
- 모든 개발이 서버에서 이루어지므로 개발 집중화를 통한 효율성 증대
JSP의 단점
- 화면 구성요소를 변경하면 JSP ⇒ 자바 ⇒ 클래스 ⇒ 서블릿 실행 과정을 거치므로, 사소한 UI 변경일지라도 매번 확인하는 데 시간이 소요된다.
- 개발자와 디자이너 간 역할 분담에 제약이 있다.
- JSP 파일의 화면 디자인 확인에도 반드시 서블릿 컨테이너 실행이 필요하다.
6.2 JSP 지시어
6.2.1 지시어란?
기본형식
<%@ 지시어 속성="값" %>
JSP 파일의 속성을 기술하는 요소
JSP 컨테이너에 해당 페이지를 어떻게 처리해야 하는지를 전달
page, include, taglib으로 나눌 수 있다.
6.2.2 page 지시어
JSP 문서는 (주석을 제외한) 첫 번째 문장이 페이지 지시어여야 한다.
JSP 페이지를 컨테이너에서 처리(서블릿으로 변환)하는 데 필요한 각종 속성을 기술.
대부분 응답 헤더로 포함되어진다.
기본 구문
<% page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" import="java.util.*" errorpage="error.jsp"%>
- language : 현제 페이지의 스크립트 언어를 지정. 실제 사용하는 언어는 java뿐이기에 쓸 필요가 없다.
- contentType : 현재 페이지의 파일 형식을 지정. 현재 text타입의 html 파일, UTF-8로 charset 지정 되었다는 것을 알려준다.
- text/html : 이런 식의 정보 표현 방식을 마임mime이라고 한다.
- pageEncoding : 현재 jsp문서가 어떤 방식으로 인코딩 되어 있는가. 우리가 만든 jsp 문서 자체의 인코딩 방식이고, contentType의 charset은 서버와 소통하는 인코딩 방식이다. 생략하면 UTF-8을 기본으로 설정한다.
- import : JSP파일 내에서 자바 코드를 직접 사용하는 경우, 일반 자바 코드와 마찬가지로 클래스에 대한 패키지 import가 요구된다. 여러 번 사용할 수 있고, 따옴표 내에서 쉼표(,)를 사용할 수도 있다.
<%@ page contentType="text/html; charset=UTF-8" import="java.time.LocalDateTime, java.util.*" %>
- errorPage : JSP 요청 처리 중 에러가 발생하는 경우, 별도의 페이지에서 처리하기 위한 속성.
더보기예외가 발생한 페이지에서 직접 예외 처리하는 경우
<%@ page contentType="text/html; charset=UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>errorThrow.jsp</title> </head> <body> <h2>현재 JSP 문서에서 예외 발생</h2> <hr /> <% try{ int num = 10 / 0; } catch(Exception e) { out.println("예외발생!<br />"); out.println("빠른 시간 안에 문제를 해결하겠습니다."); } %> </body> </html>
error.jsp로 에러처리를 넘기는 경우
<%@ page contentType="text/html; charset=UTF-8" errorPage="error.jsp" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>errorThrow.jsp</title> </head> <body> <h2>현재 JSP 문서에서 예외 발생</h2> <hr /> <% int num = 10 / 0; /* try{ } catch(Exception e) { out.println("예외발생!<br />"); out.println("빠른 시간 안에 문제를 해결하겠습니다."); } */ %> </body> </html>
error.jsp 파일도 만들어준다.
<%@ page contentType="text/html; charset=UTF-8" isErrorPage="true" %> <!-- isErrorPage="true"라는 문장을 써줘야 다른 페이지에서 받아온 에러를 처리할 수 있다. --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>error.jsp</title> </head> <body> <h2>예외 발생!</h2> <hr /> <div id="target"> <%= exception %> </div> </body> </html>
errorThrow.jsp에서 발생한 에러를 error.jsp로 연결해 처리하고 있다. 6.2.3 include 지시어
사용된 위치에 특정 파일(html, jsp)을 불러 온다.
불러온 파일의 내용을 모두 포함해 하나의 서블릿 코드로 생성된다.
하나의 jsp 파일(화면)이 실제로는 여러 파일의 조합으로 구성되는 경우.
<%@ include file="header.jsp" %> <%@ include file="body.jsp" %> <%@ include file="footer.jsp" %>
6.2.4 taglib 지시어
커스텀 태그를 사용하기 위한 지시어로, 커스텀 태그와 관련해 뒤에서 살펴본다.
6.3 템플릿 데이터와 스크립트 요소
6.3.1 템플릿 데이터 -> JSP의 화면 구성 요소
- 주로 html 파일처럼 HTML, CSS, 자바스크립트도 사용 가능
- Bootstrap, Axios같은 라이브러리 역시 사용 가능
- React, Vue와 같은 요소는 프런트엔드 개발 기술로 JSP와 함께 사용하지 않음.
6.3.2 스크립트 요소 -> 자바 코드
현재는 JSP 파일에서 직접적인 자바 코드는 거의 사용하진 않지만, 기본적인 내용을 알아두자.
- <%! %> : 선언 태그
- 멤버 변수나 추가적인 메서드를 선언하기 위해서 사용.
- <%= %> : 표현 태그
- 값을 출력하기 위한 태그
- 변수, 값을 반환하는 메서드, 간단한 계산식 등을 사용 가능.
- EL로 대체할 수 있음
- <%-- --%> : 주석
- <% %> : 스크립트릿
- 자바 코드를 직접 삽입.
- scriptlet ex1
<%@ page contentType="text/html; charset=UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>scriptlet1.jsp</title> </head> <body> <h2>Scriptlet Example1</h2> <hr /> <% for(int i=0; i < 10; i++) { out.println(i + "<br />"); } %> </body> </html>
println()을 사용했다고 출력화면이 개행되는 건 아니다. 소스가 개행이 될 뿐. html에서 개행하려면 <hr /> 사용할 것 - scriptlet ex2 : 스크립트 블럭을 분리할 수 있다.
<%@ page contentType="text/html; charset=UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>scriptlet2.jsp</title> </head> <body> <h2>Scriptlet Example2</h2> <hr /> <% for(int i=0; i < 10; i++) { %> <h4><%= i + ": " %>Hello, World!</h4> <% } %> </body> </html>
- scriptlet ex3 : scriptlet과 html태그를 이용해 테이블 만들기
<%@ page contentType="text/html; charset=UTF-8" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>scriptlet3.jsp</title> <style> table, td { border: 2px solid gray; border-collapse: collapse; } td { padding: 5px; text-align: center; } </style> </head> <body> <h2>Scriptlet Example3</h2> <hr /> <table> <% for(int i=0; i < 10; i++) { %> <tr><td><%= "Data " + i %></td></tr> <% } %> </table> </body> </html>
더보기구구단 만들기
<%@ page contentType="text/html; charset=UTF-8" %> <% String gugu = "<table>"; for(int num = 0; num < 10; num++) { gugu +="<tr>"; for(int dan = 2; dan < 10; dan++) { if(num == 0){ gugu += "<th>[ " + dan + "단 ]</th>"; } else { gugu += "<td>" + dan + " * " + num + " = " + (dan * num) + "</td>"; } } gugu +="</tr>"; } gugu += "</table>"; %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>gugu.jsp</title> <style> table, td, th { border: 2px solid gray; border-collapse: collapse; } td, th { padding: 5px; text-align: center; } </style> </head> <body> <h2>수평 구구단 </h2> <hr /> <h4>이 곳에 수평 구구단 결과를 출력하는 코드를 작성하세요.</h4> <%= gugu %> </body> </html>
스크립트릿 사용 자체를 요즘은 잘 안하는 추세지만, 사용한다면
위와 같이 html코드 시작 전에 모든 처리 후,
본문에는 한 번만 사용하도록 한다.
더보기실습1: JSP 기초 종합 예제
<%@ page contentType="text/html; charset=UTF-8" %> <%! String[] members = { "김휴고", "케이티", "임루루", "홍길동" }; int num1 = 10; int calc(int num2) { return num1 + num2; } %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JSP 종합 예</title> </head> <body> <h2>JSP 종합 예제</h2> <hr /> <h3> 1. JSP 주석 <!-- HTML 주석: 화면에서는 안 보이고 소스 보기에는 보임 --> <%-- JSP 주석: 화면과 소스 보기에서 보이지 않음 --%> </h3> <h3> 2. calc(10) 메서드 실행 결과: <%=calc(10) %> </h3> <hr /> <h3>3. include: hello.jsp <%@ include file="../chap02/hello.jsp" %></h3> <hr /> <h3>4. 스크립트(배열 데이터 출력)</h3> <ul> <% for (String name : members) { %> <li><%=name%></li> <% } %> </ul> </body> </html>
'JSP' 카테고리의 다른 글
7.3 커스텀 태그와 EL (0) 2023.09.07 7.1 JSP 응용 - 액션태그 | INCLUDE 지시어, 액션으로 페이지 구조 만들기 (1) 2023.09.01 JSP파일에서 활용가능한 주석들 : HTML, JAVA, JS, CSS, JSP (0) 2023.08.31