개발/Java

JSP란?

728x90

JSP에서 동적컨텐츠를 지원하는 웹페이지를 개발하기 위한 기술

<%로 시작하고, %>로 끝나는 특수한 태그를 이용하여 HTML에 Java 코드를 삽입할 수 있음.

Java 웹 응용 프로그램의 사용자 인터페이스 역할을 수행할 수 있도록 설계된 서블릿이다.

 

왜 JSP를 사용할까?

 

JSP는 별도의 CGI 파일 대신에 HTML 페이지 자체에 동적 요소를 포함할 수 있어 성능이 크게 향상됨.

JSP는 페이지가 요청될 때 마다 서버가 인터프리터와 대상 스크립트를 로드해야하는 CGI와 달리 서버에서 처리되기 전에 항상 컴파일 된다.

JSP는 Servlets API위에 구축된다. 따라서 

JSP는 서블릿 템플릿 엔진이 지원하는 모델인 비지니스 로직을 처리하는 서블릿과 함께 사용할 수 있음.

 

서블릿에서 콘텐츠를 출력하려면 스트림 클래스를 사용하여 출력 함수를 호출해서 코드가 길어지고, 가독성이 떨어지는 문제가 있음.

이를 개선하기 위해 HTML에 Java 소스코드를 삽입하는 방식을 도입함.

 

JSP의 구성요소

 

  • 디렉티브 : JSP 페이지에 대한 설정 정보를 지정할 때 사용됨
    • JSP 페이지에 대한 정보 지정, 웹브라우저가 전송한 데이터를 읽어오는 기능, JSP페이지에서 사용할 데이터를 생성하는 실행 코드, 웹브라우저에 문서 데이터를 전송하는 기능 필요. 
    • <%@으로 시작하고, 그 뒤에 디렉티브 이름이 위치함. 사용하려는 디렉티브에 따라서 알맞은 속성이 위치하며, %>로 디렉티브 선언이 끝남.
    • page : JSP 페이지에 대한 정보를 지정함. JSP가 생성하는 문서의 타입, 출력 버퍼의 크기, 에러 페이지 등 JSP 페이지에서 필요로 하는 정보를 설정함.
    • taglib : JSP 페이지에서 사용할 태그 라이브러리를 지정함.
    • include : JSP 페이지의 특정 영역에 다른 문서를 포함시킴.
<%@ directive attribute="value" %>

 

 

아래와 같은 디렉티브 태그들이 있다.

1 <%@ page ... %>
Defines page-dependent attributes, such as scripting language, error page, and buffering requirements.
2 <%@ include ... %>
Includes a file during the translation phase.
3 <%@ taglib ... %>
Declares a tag library, containing custom actions, used in the page

그리고 아래와 같은 속성들이 있다.

1 buffer
Specifies a buffering model for the output stream.
2 autoFlush
Controls the behavior of the servlet output buffer.
3 contentType
Defines the character encoding scheme.
4 errorPage
Defines the URL of another JSP that reports on Java unchecked runtime exceptions.
5 isErrorPage
Indicates if this JSP page is a URL specified by another JSP page's errorPage attribute.
6 extends
Specifies a superclass that the generated servlet must extend.
7 import
Specifies a list of packages or classes for use in the JSP as the Java import statement does for Java classes.
8 info
Defines a string that can be accessed with the servlet's getServletInfo() method.
9 isThreadSafe
Defines the threading model for the generated servlet.
10 language
Defines the programming language used in the JSP page.
11 session
Specifies whether or not the JSP page participates in HTTP sessions
12 isELIgnored
Specifies whether or not the EL expression within the JSP page will be ignored.
13 isScriptingEnabled
Determines if the scripting elements are allowed for use.

 

*contentType 속성과 캐릭터 셋

 

디렉티브의 contentType 속성은 JSP가 생성할 문서의 타입을 지정한다.

 

MIME : Multipurpose Internet Mail Extensions의 약자, 이메일의 내용을 설명하기 위해 정의됨.

메일뿐만 아니라 HTTP 등의 프로토콜 에서도 응답 데이터의 내용을 성명하기 위해서 MIME를 사용하고 있음.

 

import 속성

JSP 코드에서 클래스의 단순 이름을 사용할 수 있다.

<%@ page import = "java.io.*,java.util.*" %>

 

그리고 아래와 같이 컴마를 통해 여러 타입을 지정할 수 있다. 

<%@ page import = "java.io.*,java.util.*, javax.servlet.*" %>

 

스크립트 요소

  • JSP 문서의 내용을 동적으로 생성하기 위해 사용되는 것.
  • 스크립트 요소를 사용하면 사용자가 폼에 입력한 정보를 데이터베이스에 저장할 수 있으며, 데이터베이스로부터 게시글 목록을 읽어와 출력할 수도 있다. 또한 스크립트를 사용하면 자바의 다양한 기능을 사용할 수 있다. 
  • 스크립트릿 : 자바코드를 실행함
  • 표현식 : 값을 출력함
  • 선언부 : 자바 메서드를 정의
  • 기본객체 (implicit object)
    • request, response, session, application, page등 다수의 기본 객체가 존재.
    • 각각 요청 파라미터 읽어오기, 응답 결과 전송하기, 세션 처리하기, 웹 어플리케이션 정보 읽어오기 등의 기능 제공

 

1 request
This is the HttpServletRequest object associated with the request.
2 response
This is the HttpServletResponse object associated with the response to the client.
3 out
This is the PrintWriter object used to send output to the client.
4 session
This is the HttpSession object associated with the request.
5 application
This is the ServletContext object associated with the application context.
6 config
This is the ServletConfig object associated with the page.
7 pageContext
This encapsulates use of server-specific features like higher performance JspWriters.
8 page
This is simply a synonym for this, and is used to call the methods defined by the translated servlet class.
9 Exception
The Exception object allows the exception data to be accessed by designated JSP.

 

스크립트립(Scriptlet)

JSP 페이지에서 자바 코드를 실행할 때 사용하는 코드 불록.

 

아래와 같은 jsp를 웹브라우저에서 실행하면 아래의 결과와 같다.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <%
    int sum = 0;
    for (int i = 0; i < 10; i++) {
      sum = sum + 1;

    }
  %>
  1부터 10까지의 합은 <%= sum%> 입니다.
  </body>
</html>

그리고 아래와 같이, 스크립트 블록을 나눠서 구현할 수 있다.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <%
    int sum = 0;
    for (int i = 0; i < 10; i++) {
      sum = sum + 1;

    }
  %>
  1부터 10까지의 합은 <%= sum%> 입니다.

  <%
    int sum2 = 0;
    for (int i = 11; i <= 20; i++) {
      sum2 = sum2 + 1;

    }
  %>
  11부터 20까지의 합은 <%= sum%> 입니다.
  </body>
</html>

표현언어 (Expression Language)

값을 표현하는데 사용되는 새로운 스크립트 언어, JSP의 문법을 보완하는 역할을 함.

아래와 같은 기능들을 제공한다.

  • JSP의 네가지 기본 객체가 제공하는 영역의 속성 사용
  • 수치 연산, 관셰 연산, 논리 연산자 제공
  • 자바 클래스 메소드 호출 기능 제공
  • 쿠키, 기본객체의 속성 등 JSP를 위한 표현 언어의 기본 객체 제공
  • 람다식을 이용한 함수 정의와 실행.

스크립트 요소를 사용하면 JSP 코드가 다소 복잡해진다. 예를들어 아래의 코드를 표현언어로 간소화 할 수 있다.

 

  <%
    
    int a = Integer.parseInt(request.getParameter("a"));
    int b = Integer.parseInt(request.getParameter("b"));
    
  %>
   a * b = <%= a * b %>
a * b = ${param.a * param.b}

 

표준 액션 태그

 

특정한 페이지의 실행 결과를 현재 위치에 포함시킬 때 사용함.

 

<jsp:action_name attribute="value" />

아래와 같은 속성들이 있다.

1 jsp:include
Includes a file at the time the page is requested.
2 jsp:useBean
Finds or instantiates a JavaBean.
3 jsp:setProperty
Sets the property of a JavaBean.
4 jsp:getProperty
Inserts the property of a JavaBean into the output.
5 jsp:forward
Forwards the requester to a new page.
6 jsp:plugin
Generates browser-specific code that makes an OBJECT or EMBED tag for the Java plugin.
7 jsp:element
Defines XML elements dynamically.
8 jsp:attribute
Defines dynamically-defined XML element's attribute.
9 jsp:body
Defines dynamically-defined XML element's body.
10 jsp:text
Used to write template text in JSP pages and documents.

 

표현식

어떤 값을 출력 결과에 포함시키고자 할 때 사용됨.

아래와 같이 표현식에서 직접 계산해서 출력할 수 있다.

 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <%
    int sum = 0;
    for (int i = 0; i < 10; i++) {
      sum = sum + 1;

    }
  %>
  1부터 10까지의 합은 <%= 1+2+3+4+5+6+7+8+9+10%> 입니다.

 

선언부 declaration

  <%!

    public int multiply(int a, int b) {
      int c = a * b;
      return c;
    }
  %>

  선언부를 사용한 두 정수값의 곱 10 * 25 = <%= multiply(10,25)%>

  <%

위와 같이 메서드를 선언할 때 사용한다 .

 

커스텀 태그

JSP를 확장시켜주는 기능, 액션 태그와 마찬가지로 태그 형태로 기능을 제공함. 하지만 커스텀 태그는 개발자가 직접 개발해줘야 한다.

일반적으로 JSP 코드에서 중복되는 것을 모듈화 하거나 스크립트 코드를 사용할 때 발생하는 소스 코드의 복잡함을 없애기 위해 커스텀 태그를 사용한다.

커스텀 태그 중에 자주 사용하는 것들을 별도로 표준화한 태그 라이브러리가 있는데 이것이 바로 JSTL이다.

if-else 조건문 그리고 for 구문과 같은 반복 처리를 커스텀 태그를 이용해서 구현할 수 있도록 해준다.

 

*trimDirectiveWhitespaces

JSP 2.1 버전부터 새롭게 추가됨. 불필요하게 생성되는 불필요한 줄바꿈 공백 문자를 제거 가능함.

 

 

 

JSP 페이지의 인코딩과 pageEncoding 속성

 

JSP페이지가 사용할 캐릭터 셋을 결정하는 기본 과정은 다음과 같다.

1. 파일이 BOM으로 시작하지 않을 경우,

  1. 기본 인코딩을 통해 파일을 처음부터 읽고, page 디렉티브의 pageEncoding 속성을 검색함. 
  2. pageEncoding 속성을 갖고 있다면, 파일을 읽어올 때 속성값을 캐릭터 셋으로 사용한다.
  3. pageEncoding 속성이 없다면, contentType 속성을 검색한다. 
  4. 모두 해당하지 않으면 ISO-8859-1을 캐릭터 셋으로 사용한다.

2. 파일이 BOM으로 시작할 경우

  1. BOM을 이용해서 결정된 인코딩을 이용하여 파일을 읽고, page 디렉티브의 pageEncoding 속성을 검색한다.
  2. 만약 pageEncoding 속성의 값과 BOM을 이용해서 결정된 인코딩이 다르면 에러를 발생시킨다.

 

*BOM : Byte Order Mark의 약자, 바이트의 순서가 리틀엔디언인지, 빅 엔디언인지 여부를 알려주는 16비트 값이다.

 

 

 

request 기본객체

 javax.servlet.http.HttpServletRequest 객체의 인스턴스이다.

클라이언트가 페이지를 요청할 때 마다 JSP 엔진은 해당 요청을 나라태는 새 개체를 만든다.

 

요청 객체는 양식 데이터 쿠키 HTTP 메서드를 포함한 HTTP 헤더 정보를 가져오는 메서드를 제공함.

 

그리고 아래의 기능들을 제공함.

  • 클라이언트와 관련된 정보 읽기
  • 서버와 관련된 정보 읽기
  • 클라이언트가 전송한 요청 파라미터 읽기
  • 클라이언트가 전송한 요청 헤더 읽기
  • 클라이언트가 전송한 쿠키 읽기
  • 속성 처리

HttpServletRequest는 아래와 같이 정의 되어 있고,

public interface HttpServletRequest extends ServletRequest 

 

 

아래의 함수들을 제공한다.

1 Cookie[] getCookies()
Returns an array containing all of the Cookie objects the client sent with this request.
2 Enumeration getAttributeNames()
Returns an Enumeration containing the names of the attributes available to this request.
3 Enumeration getHeaderNames()
Returns an enumeration of all the header names this request contains.
4 Enumeration getParameterNames()
Returns an enumeration of String objects containing the names of the parameters contained in this request.
5 HttpSession getSession()
Returns the current session associated with the this request, or if the request does not have a session, creates one.
6 HttpSession getSession(boolean create)
Returns the current HttpSession associated with the this request or, if if there is no current session and create is true, returns a new session.
7 Locale getLocale()
Returns the preferred Locale that the client will accept content in, based on the Accept-Language header.
8 Object getAttribute(String name)
Returns the value of the named attribute as an Object, or null if no attribute of the given name exists.
9 ServletInputStream getInputStream()
Retrieves the body of the request as binary data using a ServletInputStream.
10 String getAuthType()
Returns the name of the authentication scheme used to protect the servlet, for example, "BASIC" or "SSL," or null if the JSP was not protected.
11 String getCharacterEncoding()
Returns the name of the character encoding used in the body of this request.
12 String getContentType()
Returns the MIME type of the body of the request, or null if the type is not known.
13 String getContextPath()
Returns the portion of the request URI that indicates the context of the request.
14 String getHeader(String name)
Returns the value of the specified request header as a String.
15 String getMethod()
Returns the name of the HTTP method with which this request was made, for example, GET, POST, or PUT.
16 String getParameter(String name)
Returns the value of a request parameter as a String, or null if the parameter does not exist.
17 String getPathInfo()
Returns any extra path information associated with the URL the client sent when it made this request.
18 String getProtocol()
Returns the name and version of the protocol the request uses.
19 String getQueryString()
Returns the query string that is contained in the request URL after the path.
20 String getRemoteAddr()
Returns the Internet Protocol (IP) address of the client that sent the request.
21 String getRemoteHost()
Returns the fully qualified name of the client that sent the request.
22 String getRemoteUser()
Returns the login of the user making this request, if the user has been authenticated, or null if the user has not been authenticated.
23 String getRequestURI()
Returns the part of this request's URL from the protocol name up to the query string in the first line of the HTTP request.
24 String getRequestedSessionId()
Returns the session ID specified by the client.
25 String getServletPath()
Returns the part of this request's URL that calls the JSP.
26 String[] getParameterValues(String name)
Returns an array of String objects containing all of the values the given request parameter has, or null if the parameter does not exist.
27 boolean isSecure()
Returns a boolean indicating whether this request was made using a secure channel, such as HTTPS.
28 int getContentLength()
Returns the length, in bytes, of the request body and made available by the input stream, or -1 if the length is not known.
29 int getIntHeader(String name)
Returns the value of the specified request header as an int.
30 int getServerPort()
Returns the port number on which this request was received.

 

아래의 JSP를 실행하면

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  IP <%= request.getRemoteAddr()%>
  요청정보길이 <%= request.getContentLength()%>
  요청정보 인코딩 <%= request.getCharacterEncoding()%>
  컨텐츠 타입 <%= request.getContentType()%>
  프로토콜 <%= request.getProtocol()%>
  전송방식 <%= request.getMethod()%>
  URI <%= request.getRequestURI()%>
  컨텍스트 경로 <%= request.getContextPath()%>
  서버이름 <%= request.getServerName()%>

  </body>
</html>

아래와 같은 결과를 확인할 수 있다.

 

 

 

 

요청 파라미터

 

 

HTML 폼과 요청 파라미터

 

아래의 메서드들을 제공한다.

  • String getParameter(String name) : 이름이 name인 파라미터 값을 구한다. 존재하지 않으면 null을 리턴함.
  • String[] getParameterValues(String name) : 이름이 name인 모든 파라미터 값을 구한다. 존재하지 않으면 null을 리턴함.
  • Enumeration getParameterNames() : 웹 브라우저가 전송한 파라미터의 이름 목록을 구한다.
  • Map getParameterMap() : 웹브라우저가 전송한 파라미터의 맵을 구한다.

 

요청 파라미터 인코딩

 

파라미터를 전송할 때 알맞은 캐릭터 셋을 이용해서 파라미터 값을 인코딩 함.

 

get 방식으로 파라미터 전송시 인코딩 결정 규칙

  • <a> 태그의 링크 태그에 쿼리 문자열 추가 : 웹페이지 인코딩 사용
  • HTML 폼 method 속성값을 GET으로 지정해서 폼을 전송 : 웹페이지 인코딩 사용
  • 웹브라우저 주소에 직접 쿼리 문자열을 포함하는 URL 입력 : 웹브라우저마다 다름

GET 방식으로 전달되는 파라미터 값에 대한 표준 인코딩 규칙이 정해져 있지 않아 WAS마다 GET 방식의 파라미터 값을 읽어올 때 사용하는 기본 캐릭터 셋도 다르다.

 

톰캣8에서는 기본 캐릭터셋은 UTF-8이다. 

server.xml 파일에서 <Connector>의 useBodyEncodingForURI 속성의 값을 true로 지정하고

GET 방식으로 전달된 파라미터 값을 읽어올 때 request.setChracterEncoding() 메서드로 지정한 캐릭터 셋을 사용한다.

 

또는 URIEncoding 속성을 사용할 수도 있다. URI 값을 구할 때 사용할 캐릭터 셋을 지정한다.

 

요청 헤더 정보의 처리

HTTP 프로토콜은 헤더 정보에 부가적인 정보를 담도록 하고 있다.

requset기본 객체는 이러한 헤더 정보를 읽어올 수 있는 기능을 제공함.

 

  • String getHeader(String name) : 지정한 이름의 헤더 값을 구한다.
  • Enumeration getHeaders(String name) : 지정한 이름의 헤더 목록을 구한다.
  • Enumeration getHeaderNames() : 모든 헤더의 이름을 구한다.
  • int getIntHeader(String name) : 지정한 헤더의 값을 정수 값으로 읽어온다.
  • long getDateHeader(String name) : 지정한 헤더의 값을 시간 값으로 읽어온다.

아래와 같이 jsp를 작성하여 실행시키면 

 

<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>
  <%
    Enumeration headerEnum = request.getHeaderNames();
    while(headerEnum.hasMoreElements()){
      String headerName = (String)headerEnum.nextElement();
      String headerValue = request.getHeader(headerName);
%>
      <%= headerName %> = <%= headerValue%>
  <%
    }

  %>

  </body>
</html>

위와 같은 결과를 확인할 수 있다. 웹브라우저의 종류, OS, 쿠키 정보에 따라 표시되는 정보가 달라진다.

 

The reponse Object

 

javax.servlet.http.HttpServletResponse의 인스턴스이다. 클라이언트에 대한 응답을 나타내는 객체이다.

 

새 HTTP 헤더 생성을 처리하는 인터페이스도 정의한다. 이 객체를 통해 새 쿠키, 날짜 스탬프, HTTP의 상태 코드등을 추가할 수 있다.

 

헤더 입력 정보, 리다이렉트 등의 기능을 제공한다.

 

아래와 같이 헤더를 추가할 수 있는 메서드들이 정의되어 있다.

    boolean containsHeader(String var1); // 이름이 name인 헤더를 포함하고 있을 경우 true를, 그렇지 않은 경우 false를 리턴
    
    void setDateHeader(String var1, long var2); // date를 지정함

    void addDateHeader(String var1, long var2); // date를 추가함.

    void setHeader(String var1, String var2); // var1 헤더의 값을 var2로 지정

    void addHeader(String var1, String var2); // var1 헤더의 값을 var2로 추가

    void setIntHeader(String var1, int var2); // var1 헤저에 정수값을 지정

    void addIntHeader(String var1, int var2); // var1 헤저에 정수값을 추가

 

 

웹브라우저 캐시 제어를 위한 응답 헤더 입력

 

간혹 DB에 새로운 내용이 추가되어도 브라우저에 출력되는 내용이 바뀌지 않는 경우가 있다.

이 이유는 웹브라우저가 서버가 생성한 결과를 출력하지 않고 캐시의 데이터를 출력하기 때문이다.

 

*캐시란? 동일한 데이터를 중복해서 로딩하지 않도록 할 때 사용함. 첫번째 요청시 응답 결과를 로컬 PC의 임시 보관소인 캐시에 저장함.

이후 동일한 URL에 대한 요청이 있으면 WAS에 접근하지 않기 때문에 훨씬 빠르게 응답 결과를 웹브라우저에 출력할 수 있게 된다.

따라서 JSP의 듣압 결과나 이미지, 정적인 HTML등은 캐시에 보관하여 응답 속도를 향상시킬 수 있다.

 

  • Cache-Control
    • HTTP 1.1 버전에서 지원하는 헤더로서, 이 헤더의 값을 no-cache로 지정하면 웹 브라우저는 응답 결과를 캐시하지 않는다.
    • no-cache로 설정하더라도 응답 내용을 캐시 저장소에 보관할 수 있다.
      • 예를 들어 뒤로가기 버튼을 누르면 캐시를 사용하기도 한다. 응답 결과가 캐시 저장소에 보관되지 않도록 하려면, 이 헤더에 no-store를 추가한다.
  • Pragma 
    • HTTP 1.0 버전에서 지원하는 헤더로서, 이 헤더의 값을 no-cache로 지정하면 웹브라우저는 응답 결과를 캐시에 저장하지 않는다.
  • Expries
    • HTTP 1.0 버전에서 지원하는 헤더로서, 응답 결과의 만료일을 지정한다. 만료일은 현재 시간보다이전으로 설정함으로써 캐시에 보관하지 않도록 할 수 있다.

리다이렉트를 이용해서 페이지 이동하기

 

웹 서버가 웹브라우저에게 다른 페이지로 이동하라고 응답하는 기능이다.

주의할 점이 인코딩한 쿼리 문자열을 사용해야 한다. 아래와 같이 UTF-8로 인코딩 가능

<%
	String encodedValue = URLEncoder.encode(value, "utf-8");
	response.sendRedirect("이동할 페이지")
%>

 

 

JSP의 처리 과정

 

JSP에 해당하는 서블릿이 존재하지 않을 경우

  1. 웹 브라우저에서 HTTP 요청을 보냄
  2. 웹서버는 HTTP 요청이 JSP 페이지에 대한 것임을 인식하고, 이를 JSP 엔진으로 전달함.
  3. JSP 엔진은 디스크에서 JSP 페이지를 로드하고 이를 서블릿 컨텐츠로 변환함. 이 변환에서 모든 템플릿 텍스트가 println() 문으로 변환되고 모든 JSP 요소가 Java 코드로 변환된다. 이 코드는 페이지의 해당 동적 동작을 구현함. (translation)
  4. JSP 엔진은 서블릿을 실행 가능한 클래스로 변환하고 원래 요청을 서블릿 엔진에 전달함. (compile)
  5. 서블릿 엔진은 서블릿 클래스를 로드하고 실행한다. 실행중에 서블릿은 HTML 형식으로 출력을 생성함. 출력은 HTTP 응답 내부의 서블릿 엔진에 의해 웹서버로 추가로 전달됨.
  6. 웹서버는 정적 HTML를 HTTP 응답으로 브라우저에 전달함.

 

JSP에 해당하는 서블릿이 존재하는 경우

  1. 서블릿에 클라이언트 요청을 전달함.
  2. 서블릿이 요청을 처리한 결과를 응답으로 생성.
  3. 응답을 웹브라우저에 전송함.

 

즉 JSP 페이지를 요청할 대에는 JSP를 직접 실행하는게 아니라, JSP를 자바 소스코드로 변환해서 컴파일 하여 생성한 서블릿을 실행하는 것이다.

여기서 JSP -> Java를 변환 Translation이라고 하고, 자바 코드를 서블릿 클래스로 변경하는 단계를 Compile 단계라고 한다.

 

 

 

출력 버퍼와 응답

 

JSP 페이지는 응답 결과를 곧바로 웹브라우저에 전송하지 않고 대신 buffer라고 불리는 곳에 임시로 응답 결과를 저장하고 한번에 웹브라우저에 전송함

 

그래서 아래와 같은 장점이 있다.

 

  • 데이터 전송 성능 향상
  • JSP 실행 도중에 버퍼를 비우고 새로운 내용 전송 가능
  • 버퍼가 다 차기 전까지 헤더 변경 가능.

작은 단위로 데이터를 전송하는 것이 아니라 한 번에 큰 단위로 데이터를 전송하는 것이 가능함.

<jsp:forward> 기능과 에러 페이지 처리 기능이 가능함.

JSP 페이지가 생성한 결과를 일단 버퍼에 저장하기 때문에 일정 크기가 될 때까지 웹브라우저 전송되는 데이터가 없다.

 

따라서 생성한 내용이 있다고 하더라도 버퍼에 저장된 데이터가 웹브라우저로 전송되기 전까지는 버퍼에 보관될 데이터를 지우고 새로운 내용을 전송할 수 있다. JSP 실행 과정에서 에러가 발생하면, 버퍼를 지우고 에러 화면을 출력 할 수 있다.

 

버퍼가 다 차기전까지 헤더 정보를 변경할 수 있다.

헤더 정보를 지정하는 것에 대해서 살펴봤는데 HTTP 프로토콜의 구조상 응답 상태 코드와 함께 헤더 정보를 가장 먼저 웹 브라우저에 전송해야 한다

이런 이유로 WAS는 처음 버퍼의 내용을 웹브라우저로 전송하기 전에 헤더 정보를 전송한다.

 

따라서 첫번째로 버퍼의 내용을 웹브라우저에 전송하기 전까지는헤더 정보를 얼마든지 변경할 수 있다. 하지만, 일단 버퍼 내용이 웹브라우저에 전송되면 그 이후로는 헤더정보를 변경해도 적용되지 않게 된다.

 

 

page 디렉티브에 버퍼 설정하기 : buffer 속성과 autoFlush

 

아래와 같이 버퍼의 크기를 설정할 수 있다. (단위는 kb)

일반적으로 JSP를 사용할 때 buffer를 지정하지 않는다. 기본값은 8kb 이상이다.

 

<%@ pagebuffer = '4kb' %>

 

버퍼를 사용하지 않으려면 none으로 지정하면 된다.

 

<%@ page buffer ="none" %>

버퍼를 사용하지 않으면 곧바로 웹브라우저로 전송되기 때문에

<jsp:forward> 기능을 사용할 수없고, 출력한 내용을 취소할 수 없다.

 

버퍼가 다 차면 JSP 페이지는 내용을 웹 브라우저에 전송한 후 버퍼를 비우고 새롭게 버퍼에 내용을 채우기 시작한다.

 

flush : 버퍼가 다 찼을 때 버퍼에 쌓인 데이터를 실제로 전송되어야 할 곳에 전송하고, 버퍼를 비우는것을 플러시 라고 한다.

 

page 디렉티브는 autoFlush 속성을 제공한다. 이 속성을 사용하면 버퍼가 찼을때 어떻게 처리할지를 결정할 수 있다.

 

autoFlush 속성은 true나 false로 설정 가능하다.

  • true : 버퍼가 차면 퍼버를 플러시하고 계속해서 작업을 진행.
  • false : 버퍼가 다차면 exception 발생시키고 작업을 중지함.

아래와 같이 false 일 경우

버퍼를 다 채우도록 반복문을 돌리는 코드를 실행하면 버퍼오버플로우 exception 이 발생한다.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page buffer ="1kb" autoFlush="false" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>

  <%
    for (int i = 0; i < 1000; i++) {
      %>
    1234
      <%

    }
  %>
  </body>
</html>

 

아래와 같이 true로 설정하고 jsp를 실행하면, 버퍼가 찰때 자동으로 flush 되어 웹브라우저에서 확인할 수 있다.

 

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ page buffer ="1kb" autoFlush="true" %>
<html>
  <head>
    <title>$Title$</title>
  </head>
  <body>

  <%
    for (int i = 0; i < 1000; i++) {
      %>
    1234
      <%

    }
  %>
  </body>
</html>

 

 

웹 어플리케이션 폴더 구성과 URL 매핑

 

  • WEB-INF: 웹 어플리케이션 설정 정보를 담고 있는 web.xml 파일이 위치함.
  • WEB-INF/classes: 웹 어플리케이션에서 사용하는 클래스 파일이 위치
  • WEB-INF/lib : 웹 어플리케이션에서 사용하는 jar 파일이 존재.

서블릿 2.5/JSP 2.1 규약부터는 web.xml을 반드시 포함하지 않아도 된다. 

하지만 서블릿을 직접 설정하거나, 리스너를 직접 설정하거나, 특정 URL에 속하는 JSP들에 대해 공통 속성값을 설정하는 경우

 

웹어플리케이션 폴더와 URL의 관계

 

한 웹 어플리케이션은 한개의 폴더를 차지한다. 

즉 webapps 폴더에 생성한 각 하위 폴더 구조는 앞에서 살펴본 웹 어플리케이션 폴더 구조를 따른다.

webapps 폴더에 있는 하위 폴더는 자동으로 웹 어플리케이션에 포함된다.

 

아래와 같은관계가 성립한다.

 

  • [톰캣]\webapps\[웹경로] -> http://host:port[/웹경로]

 

그리고 해당 폴더에는 ROOT 라는 특수 폴더가 존재한다. 이 폴더는 루트 웹 어플리케이션을 위한 특수 폴더이다.

http://localhost:8080/minseong 에서 /minseong를 컨텍스트 경로 context path 라고 한다.

루트 웹 어플리케이션인 경우는 컨텍스트 경로는 "" 이다.

 

URL의 첫 번째 경로와 일치하는 컨텍스트 경로를 가진 웹 어플리케이션이 존재하지 않으면, 루트 웹 어플리케이션이 요청을 처리한다.

 

그리고 request.getContextPath()를 통해서 컨텍스트 정보를 확인할 수 있다.

 

 

웹 어플리케이션 배포

 

웹 어플리케이션을 WAS에 배포하는 방법은 두가지가 있다. 

  • 대상 폴더에 파일을 직접 복사
  • war 파일로 묶어서 배포

war은 Web Application Atchive의 약자로 웹 어플리케이션의 구성 요소를 하나로 묶어 놓은 파일이다.

 

war 파일로 묶으려면 JDK의 jar 명령어를 사용하면 된다. 

 

$ jar cvf minseong.war *

c : 새로운 파일 생성

v : 세부 정보를 콘솔에 표시

f : 생성할 파일의 이름을 지정

 

 

JSP의 라이프 사이클

컨테이너가 관리하는 jsp의 생명주기

 

클라이언트 요청에 대해 클래스가 존재하지 않으면 JSP파일은 JSP 컨테이너에 의해 서블릿 형태의 자바 소스로 변환한 다음 클래스로 컴파일 한다.

 

JSP는 웹 컨테이너에 의해 최초 호출 시점에서 서블릿으로 변환되는데, 이 때 서블릿의 init() 메서드들 통해서 JSP 페이지의 jspInit() 메서드를 호출하므로 결국은 JSP 페이지가 변환된 서블릿이 초기화 되는 시점(init() 호출 시점)에 jspInit() 메서드를 호출한다. (종료할 때에도 마찬가지) 왜냐하면 아래와 같은 상속구조를 가지고 있기 때문이다.

(JSP가 서블릿으로 변환될 때 HttpJspBase를 상속받게되는데, HttpJspBase는 Servlet인 HttpServlet를 상속받은 클래스이다.)

 

 

컴파일된 JSP는 jsInit()을 통해 READY 상태가 되고 메모리에 로드된다.

이후 모든 클라이언트 접속에 따라 컨테이너에 의해  각각의 스레드를 통해 _jspService() 메서드를 호출한다.

 

_jspService()는 컨테이너에 의해 자동으로 추가되고, scriptlets 내부에 작성된 모든 코드는 이 메서드 내부에 들어간다.

 

컨테이너가 해당 서블릿 인스턴스를 제거하면  jspDestroy()를 통해 메모리에서 언로드 된다. (GC)

재정의를 통해 DB 커넥션종료 등의 작업을 할 수 있음

 

초기화 메서드와 종료 메서드는 오버라이딩 하지 않는 경우 선언만 되어있고 아무런 행동도 하지 않는 비어있는 메서드로 존재한다.

JSP 페이지 전역에 사용할 입출력 자원 등을 최초에 한번 jspInit() 메서드에서 생성하고 jspDestory() 메서드를 통해 반드시 최종적으로 자원을 반납하도록 정의 할 수 있다.

입출력 자원은 서버 및 서버가 운영되는 운영체제의 자원 관리와도 직결되므로 최초에 한 번만 초기화하고 종료될 때 반드시 close() 해주는 식으로 작성해두면 자원관리를 수월하게 할 수 있다.

<%!
     public void jspInit(){
           ~~ fileOut = new FileOutputStream()...                                        
     }
 
 
     public void jspDestroy(){  
           ~~
           fileOut.close()...
           ~~
     }
%>


 

 

결국 JSP의 생명주기를 다이어그램으로 나타내면 아래와 같다.

참고 : 컨테이너가 기본 기능을 제공하여, jspLint(), jspDestory() 메서드는 재정의 하는 것이 선택이지만

_jspService()는 재정의 불가함.

 

*톰캣이란

아파치 소프트웨어 재단에서 개발한 서블릿 컨테이너만 있는 웹애플리케이션 서버 (WAS)

웹서버와 연동하여 자바환경을 제공하여 JSP와 서블릿을 실행할 수 있는 환경을 제공함.

웹서버 상에서 Java 코드를 이용하기 위한 엔진 혹은 컨테이너 이다. 즉 Java 기반인 JSP, Servlet을이애하기 위해 Tomcat같은 자바를 이용한 엔진이 필요하다.

 

Servlet은 Tomcat이 이해할 수 있는 Java로된 웹서버용 클래스이다. 일반적인 Java와 같고, HTML형태로 출력하기 위해 print()를 사용함.

 

Servlet은 PHP, ASP에 비해 코드 작성이 복잡하다. 그래서 이 단점을 보완하기 위해 나온것이 JSP이다. HTML에 Java를 주입하는 방식이라 직관적이다. 

 

종합해보면 Tomcat은 JSP 코드로 Translation 하여 Servlet을 generate 한다. 그리고 자바 바이트 코드로 compile 하고,  

execute한다.

 

다음 포스팅에서 Tomcat에 대해서 더 구체적으로 알아보도록 하자.

출처

https://www.tutorialspoint.com/jsp/jsp_quick_guide.htm

https://javacpro.tistory.com/43

 

'개발 > Java' 카테고리의 다른 글

서블릿이란?  (0) 2021.05.19
데이터베이스부터 JDBC까지  (0) 2021.05.19
java.util 톺아보기  (0) 2021.05.18
Java Formatter  (0) 2021.05.18
classpath와 자바 옵션들  (0) 2021.05.18