JSP/Servlet | 세션과 쿠키 | 세션의 기본 조작 및 사용


쿠키는 작은 값을 보관하는 데 도움이 되지만, 그 이상의 것은 할 수 없다. 복잡한 값이나 큰 데이터를 보관 해 두는 것은 적합하지 않다. 그러나 액세스하여 각각의 사용자에 대해 어떤 값을 저장해서 두고 싶은 경우는 많다. 예를 들어 장바구니 같은 것이라면, 장바구니에 담은 상품 정보를 보관하고 둘 수 있다면 대단히 도움이 된다.

이렇게 “각 사용자마다 쿠키보다 복잡하고 큰 데이터를 보관"을 하는 경우에 사용되는 것이 “세션(session)“이다. 세션이란 서버와 클라이언트(브라우저) 사이의 연결되어 있는 동안 계속 유지 기능이다. 이 세션에 값을 저장하여 두는 것으로, 각 클라이언트에 데이터를 저장하고 관리할 수 있다.

세션은 “HttpSession"라는 클래스로 준비되어 있다. 이는 사실 인스턴스를 만들거나 할 필요가 없다. 처음부터 “session"이라는 암시 개체가 포함되어 있으며,이를 이용하여 세션을 조작할 수 있도록 되어 있다.

세션 값 저장 및 얻기

이 세션에는 값을 저장하거나 얻어오는 메소드가 준비되어 있다.

값을 저장

session.setAttribute(이름, 값);

값을 얻기

Object 변수 = session.getAttribute(이름);

세션 값은 어트리뷰트(속성)라는 형태로 구성되도록 되어 있다. setAttribute으로 속성을 설정하고 getAttribute로 지정된 속성을 얻어오는 것이다. 다만,이 “속성"이라고 하는 개념은 아무래도 감이 오지 않는 사람도 많을 것이다. 그래서 더 간단하게 “값을 설정하고 얻어오는” 형태의 메소드도 준비되어 있다.

값을 저장하기

session.putValue(이름, 값);

값을 얻기

Object 변수 = session.getValue(이름);

이 두 가지 방법은 사실 “완전히 동일한” 것이다. setAttribute와 putValue는 똑같은 동작을 하고 있으며, getAttribute와 getValue도 마찬가지이다. setAttribute에서 설정한 값을 getValue에서 꺼내는 것도 물론 가능하고, 그 반대도 마찬가지이다. 그래서 어떤거라도 선호하는 것을 사용하면 된다.

세션 접속 시간 및 해제

이 세션은 접속를 시작했을 때 시작해서, 접속해 있는 동안 계속 유지된다. 일정 시간 이상 접속을 하지 않거나 하면 세션도 종료되고 세션에 저장되어 있던 정보도 모두 삭제된다. 브라우저를 종료되었을 경우에는 따로 서버에 통보되지 않기에 실제로는 세션은 살아 있다. 이는 일정 시간 후에 사라지게 된다.

세션의 시작 시간과 경관 시간, 또는 세션 종료 등에 관한 메소드도 HttpSession에 준비되어 있다. 다음에 정리해 둔다.

세션을 시작하는 시간을 얻는다

long 변수 = session.getCreationTime();

마지막 액세스 시간을 얻기

long 변수 = session.getLastAccessedTime();

세션을 해제하기

session.invalidate();

getCreationTime과 getLastAccessedTime는 PC의 기준이 되는 날짜(1970년 1월 1일 자정)부터의 경과 밀리 초 단위로 얻는다. 또한 invalidate는 세션을 무효화하기 위한 것이며, 호출 이후에는 session 메소드 등은 모두 사용할 수 없게된다.

세션 유지시간을 지정

세션의 유지시간은 WAS의 기본 설정값으로 지정이 된다. 임의의 값으로 세션 유지시간을 늘리는 방법에 대해 알아보겠다.

코드상에서 유지시간 지정하기

session.setMaxInactiveInterval(초단위);
  • 세션 유지시간이 1시간인 경우 “3600"을 입력한다.

WEB-INF/web.xml에 유지시간 지정하기

<session-config>
    <session-timeout>분단위</session-timeout>
</session-config>
  • 세션 유지시간이 1시간인 경우 “60"을 입력한다.

위 두가지 방법은 세션에 대해 유지시간을 지정하는 모두 동일한 방식이다. 유지시간을 지정하지 않고 계속 유지 시키려면 0을 입력한다. 세션 유지시간은 해당 세션을 생성한 사용자의 브라우저 요청이 있을때마다 새롭게 세션시간을 갱신하게 된다. 세션 유지시간을 길게 하는것은 보안상 좋지 않으니, 적절하게 이용하자.

세션을 이용해 보기

그럼 실제로 세션을 사용하여 보기로 하자. 앞의 예제와 동일하게 하면 세션을 제대로 알기 힘들기에 이번에는 보낸 메시지를 점점 축적해 나가는 것을 만들어 보자.

아래와 같이 예제를 만들어 보자.

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ page import="java.util.*"%>
<%
    request.setCharacterEncoding("utf-8");
    response.setCharacterEncoding("utf-8");

    String flg = request.getParameter("check");
    if (flg != null) {
        session.invalidate();
        session = request.getSession();
    }

    long create = session.getCreationTime();
    long last = session.getLastAccessedTime();
    long time = (last - create) / 1000;
    if (time < 0)
        time = 0;

    String input = request.getParameter("input");
    if (input == null)
        input = "";

    ArrayList<String> msgs = (ArrayList<String>) session.getValue("messages");
    if (msgs == null)
        msgs = new ArrayList<String>();

    if (!input.equals(""))
        msgs.add(0, input);

    session.putValue("messages", msgs);
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Sample jsp</title>
<style>
h1 {
    font-size: 16pt;
    background: #AAFFAA;
    padding: 5px;
}
</style>
</head>
<body>
    <h1>Sample jsp page</h1>
    <p>이 페이지는 샘플입니다.</p>
    <table>
        <form method="post" action="helo.jsp">
            <tr>
                <td>입력</td>
                <td><input type="text" id="input" name="input"></td>
            </tr>
            <tr>
                <td></td>
                <td><input type="checkbox" id="check" name="check"> <label for="check">초기화</label></td>
            </tr>
            <tr>
                <td></td>
                <td><input type="submit" value="송신"></td>
            </tr>
        </form>
    </table>
    <hr>
    <p>(<%=time%> sec.)</p>
    <ol>
        <%
            for (int i = 0; i < msgs.size(); i++) {
        %>
        <li><%=msgs.get(i)%></li>
        <%
            }
        %>
    </ol>
</body>
</html>

액세스하면 입력 필드가 있는 화면이 나타난다. 거기에 뭔가 써서 보내면 그것이 아래에 표시한다. 보낼 때마다 그것이 목록의 맨 위에 추가된다. 보낼 때에 “초기화"의 체크 박스를 ON으로 해두면 세션을 초기화하고 새 메시지를 추가한다.

※ GAE에서 세션 사용 주의 사항

이 세션 이용의 샘플을 Google App Engine에서 동작시킬 경우, 주의해야 것은 “GAE에서 세션하기 위해서는 따로 ON으로 설정해야 한다"는 점이다. 프로젝트에 “appengine-web.xml"파일을 연다. 이는 GAE의 여러 설정을 담은 XML 파일이다. 이 가운데에 <appengine-web-app> 태그가 있다. 이 태그에 최초 설정이 작성되어 있다. 이 태그 내에

<sessions-enabled>true</sessions-enabled>

이러한 태그를 작성한다. 이제 세션을 사용할 수 있게 되었다. 이것을 잊으면 세션 기능은 움직이지 않기 때문에 주의하도록 하자.

이번은 ArrayList를 세션에 저장하고 있다. 메시지가 전송될 때마다 이 ArrayList에 추가된다.

ArrayList<String> msgs = (ArrayList<String>)session.getValue("messages");
if (msgs == null)
    msgs = new ArrayList<String>();

먼저 getValue으로 “messages"로 저장해 둔 ArrayList를 가져온다. 이것이 null 인 경우, 새로운 ArrayList 인스턴스를 만든다.

이렇게 ArrayList가 준비되면 전송된 텍스트를 맨 앞에 add하고 다시 세션에 보관한다.

session.putValue("messages", msgs);

샘플에는 세션을 시작한 이후로 경과 시간(초)을 표시한다. 이는 미리 경과 시간(초)을 계산하여 변수에 담아두고, 그것을 <%= %> 태그로 표시하고 있을 뿐이다.

long create = session.getCreationTime();
long last = session.getLastAccessedTime();
long time = (last - create) / 1000;
if (time < 0)
    time = 0;

getCreationTime과 getLastAccessedTime을 각각 변수로 얻어내어, 마지막 액세스 시간을 시작 시간에서 값을 빼고, 1000으로 나누면 경과한 초수를 알 수 있다. 의외로 간단하다. 마지막으로, “초기화” 체크가 ON일 때의 처리도 보도록 하자.

String flg = request.getParameter("check");
if (flg != null) {
    session.invalidate();
    session = request.getSession();
}

체크 박스는 체크가 ON이면 값이 전송되지만, OFF라면 값 자체가 보내지지 않는다. 따라서 request.getParameter( "check")으로 얻어낸 값이 null이면 OFF, null가 아니면 ON이라고 판단 할 수 있는 것이다.

ON인 경우에는 invalidate에서 세션을 삭제한다. 그 후으로는 다시 세션을 시작하고 전송된 값을 보관 해 두지 않으면 안된다. 그래서 request.getSession()라는 것으로, HttpSession을 다시 가져오고 있다. 암묵 객체인 session은 request의 “getSession"으로 세션을 얻어 올 수 있다.

우선 이것으로 세션 값의 보관 및 세션을 종료한 후에 재시작 등의 기본 조작을 할 수있게 되었다!