본문 바로가기
Servlet & JSP

Servlet & JSP의 4가지 Scope

by kmmguumnn 2018. 7. 1.

Servlet과 JSP를 개발하다보면 변수를 많이 다루게 된다. 변수를 어떤 범위 내에서 사용하기 위해서는 스코프(scope)라는 것에 대해서 알아야 한다.



위의 그림처럼, Servlet과 JSP에서는 Page, Request, Session, Application의 4가지 Scope이 있다.




1) (JSP) Page scope

실제 선언된 JSP 페이지 내에서만 사용할 수 있는 것. 페이지 내에서 지역변수처럼 사용.


  • PageContext 추상 클래스를 사용한다.
  • JSP 페이지에서 pageContext라는 내장 객체(Implicit Object)로 사용 가능하다.
    다른 것 필요 없이, pageContext이름.setAttribute(), pageContext이름.getAttribute() 등의 방법으로 바로 사용하면 된다.
  • forward가 될 경우 해당 Page scope에 지정된 변수는 사용할 수 없다.
    어떤 페이지로 요청이 들어온 뒤, 다른 페이지로 forward 될 경우 이전 page scope내에 있던 변수는 forward 된 page scope 내에서는 사용할 수 없다.
    cf) Request는 forward와 상관 없이, 한번 요청 후 응답할 때까지 계속 유지된다.
  • 사용방법은 Application scope나 Session scope, request scope와 같다.
  • 마치 지역변수처럼 사용된다는 것이 다른 Scope들과 다른 점이다.
  • pageScope은 지역변수와 별 차이가 없기 때문에 많이 쓰이지 않지만, 종종 필요한 경우가 있다.
    JSP에서 pageScope에 값을 저장한 후 해당 값을 EL 표기법 등에서 사용할 때, 지역 변수처럼 해당 JSP나 Servlet이 실행되는 동안에만 정보를 유지하고자 할 때 사용된다.



2) Request scope

클라이언트로부터 하나의 요청이 들어와서 서버가 일을 수행한 후 응답을 보낼 때까지, 계속 사용할 수 있는 scope. 


  • Web container 안에 있는 Servlet에 대한 http 요청을, WAS가 받아서 웹 브라우저에게 응답할 때까지 변수값을 유지하고자 할 경우 사용한다.
    모든 요청이 들어올 때마다, WAS는 request 객체와 response 객체를 만든다. forward 여부 등과 상관없이, 하나의 요청이 들어와서 응답이 나갈 때까지 계속 유지된다.

  • Servlet의 service() 메소드가 끝날 때 Request Scope가 끝난다(request 객체가 없어진다).
  • JSP에서는 request 내장 변수를 사용한다.
  • Servlet에서는 HttpServletRequest 객체를 사용한다.
  • 값을 저장할 때는 request 객체의 setAttribute() 메소드를 사용한다.
    값을 읽어 들일 때는 request 객체의 getAttribute() 메소드를 사용한다.
  • 사용목적: forward 시 값을 유지하고자 사용한다.
  • 앞선 forward에 대한 포스트에서, forward 하기 전에 request 객체의 setAttribute() 메소드로 값을 설정한 후, Servlet이나 JSP에게 결과를 전달하여 값을 출력하도록 하였는데, 이렇게 forward 되는 동안 값이 유지되는 것이 Request scope를 이용한 것이다.




3) Session scope

session 객체가 생성되고 소멸될 때까지

request는 하나의 요청과 응답이 나갈 때까지이지만, Session scope은 session 객체가 만들어져서 소멸될 때까지이므로, 하나가 아닌 여러 개의 요청이 들어와도 계속 남아있다.


  • 웹 브라우저 별로 변수를 관리하고자 할 경우 사용한다. 보통 웹 브라우저를 클라이언트라고 지칭하는데, 이는 여러 개가 있을 수 있다. Session scope은 하나의 클라이언트마다 객체를 만들어서 관리하는 것이다. 따라서 session scope은 한 클라이언트 내의 여러 개의 request들을 다 cover한다.
  • 웹 브라우저간의 탭 간에는 세션정보(상태정보)가 공유되기 때문에, 각각의 탭에서는 같은 session 정보를 사용할 수 있다.
  • Request scope과 달리, 하나의 session scope 내에서는 하나의 request가 끝나도 해당 session 객체는 계속 유지될 것이다. 미리 지정해 놓은 시간이 초과되거나, 탭이 닫히는 경우에 session이 종료된다. 즉 request보다는 정보를 오래 유지하게 되는 것이다(☞ 상태정보 유지).
  • HttpSession 인터페이스를 구현한 객체를 사용한다.
  • JSP에서는 session 내장 변수를 사용한다.
  • Servlet에서는 HttpServletRequestgetSession() 메소드를 이용하여 session 객체를 얻는다. (여기서 Request의 메소드를 사용하는 이유는, session 객체가 어떤 클라이언트의 요청인지 알아야 하기 때문)
  • 값을 저장할 때는 session 객체의 setAttribute() 메소드를 사용한다.
    값을 읽어 들일 때는 session 객체의 getAttribute() 메소드를 사용한다.
  • 쇼핑몰의 장바구니처럼 사용자 별로 유지되어야 할 정보가 있을 때 사용한다.




4) Application scope

하나의 application이 생성되고 소멸될 때까지 계속 유지. 

Eclipse에서 하나의 Project가 하나의 Application이라고 생각하면 되고, 하나의 Server에는 여러 개의 Web application이 존재할 수 있다.


  • 웹 어플리케이션이 시작되고 종료(혹은 다시 시작)될 때까지 변수를 사용할 수 있다.
  • ServletContext 인터페이스를 구현한 객체를 사용한다.
  • JSP에서는 application 내장 객체를 이용한다.
  • Servlet의 경우는 getServletContext() 메소드를 이용하여 application 객체를 이용한다.
  • 웹 어플리케이션 하나당 하나의 application 객체가 사용된다.
  • 값을 저장할 때는 application객체의 setAttribute() 메소드를 사용한다.
    값을 읽어 들일 때는 application객체의 getAttribute() 메소드를 사용한다.
  • 모든 클라이언트가 공통으로 사용해야 할 값들이 있을 때 사용한다.
    하나의 application scope는 여러 클라이언트들이 사용할 수 있기 때문이다.



 Name 

 Accessibility 

 Lifetime 

 Request

 Current, included, or forwarded pages

 Until the response is returned to the user.

 Session

 All requests from the same browser within session timeout

 Until session timeout or session ID invalidated
 (such as user quits browser).

 Application

 All request to same Web application

 Life of container or explicitly killed
 (such as container administration action).






그럼 마지막으로, application scope를 활용한 간단한 예제를 만들어 보자.

ApplicationScope01과 ApplicationScope02라는 Servlet을 2개 만들고, applicationScope01이라는 JSP를 1개 만든다.


ApplicationScope01 Servlet에서는 application scope로 value라는 변수를 만들고 1을 저장한다.

ApplicationScope02 Servlet에서는 application scope로 저장된 value의 값에 1을 더한 후 그 결과를 출력한다.

applicationScope01 JSP에서는 application scope로 저장된 value의 값에 2를 더한 후 그 결과를 출력한다.




    @WebServlet("/ApplicationScope01")
    public class ApplicationScope01 extends HttpServlet {
        private static final long serialVersionUID = 1L;

        public ApplicationScope01() {
            super();
        }

        protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
            response.setContentType("text/html; charset=utf-8");
            PrintWriter out = response.getWriter();
            
            ServletContext application = getServletContext();
            int value = 1;
            application.setAttribute("value", value);
            
            // 응답 결과 출력
            out.println("<h1>value : " + value + "</h1>");
        }
    }

ApplicationScope01.java




    @WebServlet("/ApplicationScope02")
    public class ApplicationScope02 extends HttpServlet {
        private static final long serialVersionUID = 1L;

        public ApplicationScope02() {
            super();
        }

        protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
            response.setContentType("text/html; charset=utf-8");
            PrintWriter out = response.getWriter();
            
            ServletContext application = getServletContext();
            try {
                int value = (int) application.getAttribute("value");
                value++;
                application.setAttribute("value", value);
                
                // 응답 결과 출력
                out.println("<h1>value : " + value + "</h1>");  
            } catch (NullPointerException e) {  // Application02가 먼저 실행되어 value 값이 설정되어 있지 않은 경
                out.print("value의 값이 설정되지 않았습니다.");
            }
        }
    }

ApplicationScope02.java




<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<%
try {
int value = (int)application.getAttribute("value");
value += 2;
application.setAttribute("value", value);
%>
<h1><%=value %></h1>
<%
} catch (NullPointerException e) {
%>
<h1>설정된 값이 없습니다.</h1>
<%
}
%>
</body>
</html>

applicationScope01.jsp




먼저 ApplicationScope01 Servlet을 실행하면, value 값이 1로 출력된다.

이후 ApplicationScope02 Servlet을 실행하면, value 값에 1이 더해져 2가 출력된다.

마지막으로 applicationScope01 JSP를 실행하면, value 값에 2가 더해져 4가 출력된다.


계속해서 applicationScope01 JSP를 실행할 때마다, value 값에 2가 더해진 값이 출력된다.

만약 ApplicationScope02 Servlet부터 실행하게 되면, value 변수가 지정되지 않은 상태에서 값을 가져오려 하므로 NullPointerException이 발생된다.


또한 다시 ApplicationScope01 Servlet을 실행하면 value 값은 1로 초기화되며, 그 상태에서 다른 브라우저(클라이언트)를 열어서 해당 URL로 요청한다 해도 값은 똑같은 상태인 것을 알 수 있다. 하나의 프로젝트 내에서 application 객체에 값을 저장했기 때문에, 클라이언트가 달라져도 같은 application scope 안에서 변수값이 계속 유지되는 것이다.












참고자료


APPLICATION, REQUEST, SESSION AND PAGE SCOPES IN SERVLETS AND JSPS on JAVAEEE.com

J2EE Web Component Developer: Servlet Container Model on Pearson






'Servlet & JSP' 카테고리의 다른 글

EL(Expression Language)과 JSTL(JSP Standard Tag Library)  (1) 2018.07.01
Forward, 그리고 Servlet & JSP의 연동  (0) 2018.06.30
Redirect  (0) 2018.06.29
JSP 기초  (0) 2018.06.29
Servlet 기초  (0) 2018.06.29

댓글