서버는 클라이언트가 요청한 대로 필요한 서블릿을 선택하여 사용한다. 이후 WAS는 사용이 끝난 서블릿을 날려버린다. 하지만 데이터가 유지되어야하는 경우도 있다. 로그인을 하거나, 물건을 구매할 때와 같은 상황이다. 이럴 때 이용할 수 있는 객체가 바로 application과 session, cookie이다.
어플리케이션 저장소의 경우, 생성되고 소멸될 때 까지 유지된다. 이클립스의 경우 하나의 프로젝트가 하나의 어플리케이션이라고 생각하면 되고, 하나의 서버에서는 여러개의 웹 어플리케이션이 존재할 수 있다.
어플리케이션 저장소의 경우, 서버에 저장공간을 두며 데이터는 전역범위로 사용되고 WAS가 시작해서 종료될 때 까지 유지되기 때문에 가장 넓은 범위의 상태유지 방법이라고 볼 수 있다.
📌 Application 사용법
// 저장소 선언 ServletContext application = request.getServletContext(); // 데이터 저장 application.setAttribute("키", 값); // 데이터 사용 (데이터는 object타입이기에, 형변환이 필요하다) application.getAttribute("키");
Session은 내장객체로서 브라우저마다 한 개씩 존재하고, 고유한 sessionID를 생성한 후 정보를 추출한다. Application와 사용 범위가 다른데, Application의 경우 전역적인 범위를 가지지만, Session의 경우 접근하는 클라이언트 별로 별도의 SessionID를 부여받는다. 둘 다 서버에 데이터를 저장하는 것은 동일하지만, App의 경우 서버에 값을 전부 저장해놓는 것에 반해, 세션의 경우 개별적인 공간을 부여 받는 것이다.
이러한 세션ID의 경우엔 동일 브라우저에선 같은 SID값이 유지되기 때문에, 한 브라우저에서 다른 창을 열어도 그대로 유지된다. 하지만 새로운 브라우저를 열게 되면 세션ID가 달라지기 때문에 세션값이 사라지게 된다. 크롬에서 한 사이트에 로그인을 하고 익스플로러로 그 페이지를 열어도 로그인이 되지 않는 것이 그 예시이다.
📌 Session 사용법
// 저장소 선언 HttpSession session = request.getSession(); // 세션 값 설정 session.setAttribute("세션 아이디", 값); // 세션 값 가져오기 (object 타입이기에 형변환해서 사용) session.getAttribute("세션 아이디"); // 세션 시간 설정 session.setMaxInactiveInterval(60*60); // 60분동안 세션유지 session.setMaxInactiveInterval(-1); // 세션 시간 무한대 설정 // 세션 값 삭제 session.removeAttribute("세션 아이디"); // 세션 전체 제거, 무효화 session.invalidate();
쿠키의 경우 위 두 가지 경우와 다르게 서버가 아닌, 클라이언트에 데이터를 저장하게 된다. 또한 위 두 가지 경우가 object 형식으로 저장된 것에 반해 쿠키는 text 형태로 저장된다. 클라이언트에 총 300개의 쿠키를 저장할 수 있으며, 하나의 도메인 당 20개의 쿠키를 가질 수 있다. 이러한 쿠키는 로그인 시 "아이디나 비밀번호를 저장하시겠습니까?" 나, "오늘 이 창을 다시 보지 않기"와 같은 곳에 사용한다.
쿠키는 사용 방법이 독특한데, 우선 클라이언트는 서버에 요청을 보내면, 서버는 쿠키를 실은 응답을 보낸다. 그러면, 다시 클라이언트는 쿠키에 데이터를 담아 서버에 보내게 되고, 그에 해당하는 응답을 서버가 보내준다.
쿠키 사용법의 경우에는 짜여진 코드를 보며 확인해보려고 한다. 먼저 계산 기능을 하는 HTML을 만들어준다.
전체적인 코드의 구조는, 사용자가 숫자값을 입력하고 연산자 (+나 -)를 입력하게 되면, 쿠키에 해당 값과 연산자를 함께 저장해준다. 이후 마지막 값과 = 연산자를 누르게 되면, 해당 쿠키에서 저장해놨던 값과 연산자를 꺼내어 마지막 값을 붙여 계산한 뒤, 화면에 값을 출력해줄 것이다.
먼저 쿠키를 담아줄 서블릿을 제작해주는데, 쿠키는 배열의 형태로 객체를 생성해준다.
Cookie[] cookies = arg0.getCookies();
그 이후로는 HTML에서 받아올 데이터를 String타입의 변수로 잡아준다.
Cookie[] cookiew = arg0.getCookiew(); PrintWriter out = arg1.getWriter(); // HTML에서 넘어올 숫자값과, 연산기호 데이터 String value_ = arg0.getParameter("value"); String op = arg0.getParameter("operator");
변수를 모두 설정해 주었으면, String 타입으로 받아온 숫자값 value_를, int타입으로 파싱해서 새로운 변수 value에 담아준다. 이 때 값이 입력되어있을 때만 파싱을 해주도록 조건문을 짜준다.
Cookie[] cookies = arg0.getCookies(); PrintWriter out = arg1.getWriter(); String value_ = arg0.getParameter("value"); String op = arg0.getParameter("operator"); int value = 0; // value_에 데이터가 담겨있을 때만 int로 파싱하여 value로 담아줌 if( value_ != null && !value_.equals("")){ value = Integer.parseInt(value_); }
그 뒤, 먼저 +나 -를 눌렀을 때 쿠키에 정보를 담아줄 처리를 해준다. 쿠키라는 새로운 객체를 만들어주며, key와 value값을 넣어주면 된다. 이 때, 키와 값엔 반드시 String 타입으로 담아줘야한다.
// int인 value의 타입을, 쿠키에 담기 위해 String.valueOf으로 형변환 Cookie valueCookie = new Cookie("value", String.valueOf(value)); // 연산기호인 op의 경우 애초에 String 타입이라 그대로 받아줌 Cookie opCookie = new Cookie("op", op);
이후, response에 쿠키를 담아서 사용자의 컴퓨터에 다시 쏴준다.
Cookie valueCookie = new Cookie("value", String.valueOf(value)); Cookie opCookie = new Cookie("op", op); arg1.addCookie(valueCookie); arg1.addCookie(opCookie);
이제 = 연산자를 눌렀을 때 일어나는 조건문을 짜주려고 한다. 기존 쿠키에 담겨있는 값을 y에 할당하고, 새로 담아줄 값을 x에 담기위해, 0으로 초기화 시켜준다. operator의 경우엔 새로 담아줄 연산자 이고, result는 마지막에 출력할 값을 담을 변수이다.
if(op.equals("=")){ int x = 0; int y = value; String operator = ""; int result = 0; for( Cookies c : cookies ){ if(c.getName().equals("value"){ x = Integer.parseInt(c.getValue()); break; } } for( Cookies c : cookies){ if(c.getName().equals("op")){ operator = c.getValue(); break; } } if(operator.equals("+"){ result = x + y; }else{ result = x - y; } out.println("결과 값 : " + result); }
우선 cookies라는 객체배열안에 valueCookie와 opCookie가 담겨있는데, 이를 for문을 태워서 객체의 이름이 "value"라는 방에 도달할 때 까지 반복시켜준다. 해당 방에 도착하면 x에 getValue()메소드를 이용하여 값을 꺼내 x에 할당해준다. 해당 과정이 끝나면 break를 이용하여 for문을 탈출해준다.
연산자의 경우에도 값과 마찬가지로 op라는 객체 이름을 발견하면 operator변수에 해당 값을 할당해주고 for문을 탈출한다.
이후 마지막으로 입력한 연산자가 +라면 기존 쿠키에 있던 값 y와 새롭게 들어온 값 x를 더해 result에 할당시켜주고, -라면 빼준다. 이후 결과를 출력시켜주면 된다. 전체 코드의 모습은 아래와 같다.
@WebServlet("/calc") public class Calculator extends HttpServlet{ @Override protected void service(HttpServletRequest arg0, HttpServletResponse arg1) throws ServletException, IOException{ Cookie[] cookies = arg0.getCookies(); PrintWriter out = arg1.getWriter(); String value_ = arg0.getParameter("value"); String op = arg0.getParameter("operator); int value = 0; if(value_ != null && value_.equals("")){ value = Integer.parseInt(value_); } if(op.equals("=")){ int x = 0; int y = value; String operator = ""; int result = 0; for(Cookie c : cookies){ if(c.getName().equals("value"){ x = Integer.parseInt(c.getValue()); break; } } for(Cookie c : cookies){ if(c.getName().equals("op"){ operator = c.getValue(); break; } } if(operator.equals("+")){ result = x + y; } else { result = x - y; } out.println("결과 값 : " + result); }else{ Cookie valueCookie = new Cookie("value", String.valueOf(value)); Cookie op = new Cookie("op", op); arg1.addCookie(valueCookie); arg1.addCookie(opCookie); arg1.sendRedirect("calc.html") } } }