본문 바로가기
☕ Java 웹 프로그래밍/Servlet & JSP

[Servlet&JSP] Application, Session, Cookie 정리

by 일단연 2023. 6. 1.

* 본 글은 [뉴렉처]의 Servlet&JSP 프로그래밍 강의를 듣고 정리한 글입니다.

 

2020 Servlet&JSP 프로그래밍

 

www.youtube.com

 

Application, Session, Cookie 정리

Application, Session, Cookie 비교

  Application Session Cookie
공통점 상태 저장을 위한 값을 가지고 있는 저장소
사용범위 애플리케이션 전역 범위에서 사용하는 저장공간 세션 범위(특정 사용자)에서 사용하는 저장공간 • Web Browser별 지정한 path 범주 공간     ◦ 서버에 부담을 주지 않는 자료구조
   ◦ 서버의 생명주기와 관계없이 클라이언트가 데이터를 가질 수 있음
생명주기 WAS가 시작해서 종료될 때까지 세션이 시작해서 종료될 때까지 Browser에 전달된 시간부터 만료시간까지
저장위치 WAS(서버)의 메모리 WAS(서버)의 메모리 • maxAge 설정 없으면 > Web Browser(클라이언트)의 메모리
• maxAge 설정하면 > 외부 파일(영구저장소)

 

특정 상태 값을 오래(예: 1년 이상) 유지할 땐, 어떤 저장소를 쓸까?

  • 무조건 Cookie
  • Session은 오랜 기간 값을 저장할 수도 없을 뿐더러, 저장하고 있다고 해도 세션에 특정 상태 값이 저장되어 있는 곳을 사용자가 쓸 수 없음
    • 기본적으로 사용자를 식별하는 SID는 쿠키로 전달됨
      • 브라우저를 닫으면 쿠키는 사라짐
      • 브라우저를 다시 켜면
        • 그 사용자는 브라우저를 끄기 전의 사용자로 인식되지 않음 (SID가 사라졌으니까)
        • 해당 사용자는 다른 SID를 발급받고 Session에는 그 SID에 맞는 공간이 새로 할당됨 > 서버 자원 낭비

 

특정 URL과 관련된 특정 상태 값을 갖고 있을 땐, 어떤 저장소를 쓸까?

  • 무조건 Cookie
  • 특정 URL로 언제 요청이 올지 모르는데 Session을 써서 서버 자원을 낭비할 순 없음

 

Cookie의 옵션

옵션명 설명 형태
path path라고 하는 특정 URL에 대해서만 쿠키 전달 쿠키객체명.setPath(”path”);
maxAge Browser에 쿠키를 전달한 시간부터 만료시간까지 쿠키를 외부 파일에 저장해 그 기간 동안 쿠키 사용 가능 (브라우저와 상관없음) 쿠키객체명.setMaxAge(만료날짜);

 

Application 메소드

메소드 리턴타입 설명
setAttribute(String name, Object value) void 이름이 name인 속성의 값을 value로 지정
getAttribute(String name) Object - 이름이 name인 속성읠 값을 구함
- 지정한 이름의 속성이 존재하지 않을 경우 null을 리턴
removeAttribute(String name) void 이름이 name인 속성을 삭제
getAttributeNames( ) java.util Enumeration 속성의 이름 목록을 구함

 

Session 메소드

메소드 리턴타입 설명
setAttribute(String name, Object value) void 지정한 이름으로 객체를 설정
getAttribute(String name) Object 지정한 이름의 객체를 반환
invalidate( ) void • Session 저장소를 비울 때 사용하는 메소드 (setAttribute( )메소드로 설정했던 것들을 지움)
• 세션에서 사용되는 객체들을 바로 해제 (사용자 요청이 계속 올지 아닐지 알 수 없으니까)
setMaxInactiveInterval(int interval) void • 세션 타임아웃을 정수(초)로 설정
• 세션 타임아웃: 이 시간 동안 사용자 요청이 안 오면 Session 저장소를 지우도록 제한시간을 주는 것
• 기본 타임아웃은 30분이지만, 개별적으로 변경할 수도 있음
• 1초 남은 상태에서 새로운 요청이 오면 타임아웃이 다시 30분으로 리셋되면서 다음 타임아웃이 진행됨
• 타임아웃이 경과되는 순간 해당 타임아웃의 SID를 갖고 있는 사용자 요청이 오면 그 요청은 새로운 사용자 요청으로 인식됨
   ◦ 유효하지 않은 SID가 되었기 때문에 해당 Session의 값들은 메모리에서 수거됨
isNew( ) boolean 세션이 새로 생성되었는지를 확인
getCreationTime( ) long • 세션이 시작된 시간을 반환
• 1970년 1월 1일을 시작으로 하는 밀리초
getLastAccessedTime( ) long • 세션이 마지막으로 요청된 시간을 반환
• 1970년 1월 1일을 시작으로 하는 밀리초

 

Application을 사용하는 서블릿

package com.newlecture.web;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/calc2")
public class Calc2 extends HttpServlet {
  @Override
  protected void service(HttpServletRequest request
                        , HttpServletResponse response)
                        throws ServletException, IOException
  {
    //서블릿 컨텍스트 변수 생성
    ServletContext application = request.getServletContext();
		
    //response의 인코딩 방식 지정
    response.setContentType("text/html; charset=UTF-8");
    response.setCharacterEncoding("UTF-8");
		
    PrintWriter out = response.getWriter();
		
    String v_ = request.getParameter("v");
    String op = request.getParameter("operator");
		
    //기본값 처리
    int v = 0;
    if(!v_.equals("")) {v = Integer.parseInt(v_);}
		
    //값을 계산
    if(op.equals("=")) {
      int x = (Integer)application.getAttribute("value");
      int y = v;
      String operator = (String)application.getAttribute("op");
			
      int result = 0;
			
      if(operator.equals("+")) {
        result = x + y;
      } else {
        result = x - y;
      }
      response.getWriter().printf("계산 결과는 %d\\n", result);
    }
    //값을 저장
    else {
      application.setAttribute("value", v);
      application.setAttribute("op", op);
    }
  }
}

 

Session을 사용하는 서블릿

package com.newlecture.web;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/calc2")
public class Calc2 extends HttpServlet {
  @Override
  protected void service(HttpServletRequest request
                        , HttpServletResponse response)
                        throws ServletException, IOException
  {
    ServletContext application = request.getServletContext();
    HttpSession session = request.getSession();
		
    //response의 인코딩 방식 지정
    response.setContentType("text/html; charset=UTF-8");
    response.setCharacterEncoding("UTF-8");
		
    PrintWriter out = response.getWriter();
		
    String v_ = request.getParameter("v");
    String op = request.getParameter("operator");
		
    //기본값 처리
    int v = 0;
    if(!v_.equals("")) {v = Integer.parseInt(v_);}
		
    //값을 계산
    if(op.equals("=")) {
      int x = (Integer)application.getAttribute("value");
      int y = v;
      String operator = (String)application.getAttribute("op");
			
      int result = 0;
			
      if(operator.equals("+")) {
        result = x + y;
      } else {
        result = x - y;
      }
      response.getWriter().printf("계산 결과는 %d\\n", result);
    }
    //값을 저장
    else {
//    application.setAttribute("value", v);
//    application.setAttribute("op", op);
    
      session.setAttribute("value", v);
      session.setAttribute("op", op);
    }
  }
}

 

Cookie를 사용하는 서블릿

package com.newlecture.web;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/calc2")
public class Calc2 extends HttpServlet {
  @Override
  protected void service(HttpServletRequest request
                        , HttpServletResponse response)
                        throws ServletException, IOException
  {
    ServletContext application = request.getServletContext();
    HttpSession session = request.getSession();
    Cookie[] cookies = request.getCookies();
		
    //response의 인코딩 방식 지정
    response.setContentType("text/html; charset=UTF-8");
    response.setCharacterEncoding("UTF-8");
		
    PrintWriter out = response.getWriter();
		
    String v_ = request.getParameter("v");
    String op = request.getParameter("operator");
		
    //기본값 처리
    int v = 0;
    if(!v_.equals("")) {v = Integer.parseInt(v_);}
		
    //값을 계산
    if(op.equals("=")) {
//    int x = (Integer)application.getAttribute("value");

      int x = 0;
      for(Cookie c : cookies) {
        if(c.getName().equals("value")) {
          x = Integer.parseInt(c.getValue());
          break;
        }
      }

      int y = v;
//    String operator = (String)application.getAttribute("op");
			
      String operator = "";
      for(Cookie c : cookies) {
        if(c.getName().equals("op")) {
          operator = c.getValue();
          break;
        }
      }

      int result = 0;
			
      if(operator.equals("+")) {
        result = x + y;
      } else {
        result = x - y;
      }
      response.getWriter().printf("계산 결과는 %d\\n", result);
    }
    //값을 저장
    else {
//    application.setAttribute("value", v);
//    application.setAttribute("op", op);
    
//    session.setAttribute("value", v);
//    session.setAttribute("op", op);

      Cookie valueCookie = new Cookie("value", String.valueOf(v));
      Cookie opCookie = new Cookie("op", op);
      valueCookie.setPath("/calc2");
      valueCookie.setMaxAge(24*60*60);
      opCookie.setPath("/calc2");
      response.addCookie(valueCookie);
      response.addCookie(opCookie);
    }
  }
}