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


Web에서는 모든 데이터는 네트워크 건너편에 있다. 예전에는 로컬 환경에 많은 데이터를 둘 수 없었다. HTML5이 되어 여러가지로 저장할 수 있게 되면서 완전히 Web의 모습도 바뀌어 왔다. HTML5가 등장 할 때까지 브라우저에 데이터 등을 저장할 수 있는 기능이라고 하면 ‘쿠키(cookie)‘뿐이었다.

쿠키를 이용하면 브라우저에 약간의 데이터를 저장하고 둘 수 있다. 이 쿠키의 역할은 그것뿐이다. “브라우저와 서버 사이에서 데이터를 주고 받는 정보를 교환할 수 있다"는 점에 있다. 각각의 클라이언트(Web 브라우저)에 따라 데이터를 보관하고 둘 수 있기에 여러가지로 활용을 할 수 있다. 예를 들어, ID를 할당하여 각 클라이언트를 식별하는데 사용할 수 있고, 마지막으로 액세스한 일시 등의 정보를 보관할 수도 있다.

최근 들어, HTML5가 로컬에 각종 정보를 저장할 수 있게 되어 왔지만, 이는 JavaScript를 통해서만 필요한 정보를 추출할 수 없기 때문에, 서버 사이드에서의 이용은 몹시 번거롭다. 또한 HTML5를 지원하지 않는 브라우저도 여전히 있다. 클라이언트와 서버 사이에서 원활하게 교환할 수 있는 “클라이언트 측에 저장할 수 있는 데이터"로는 쿠키의 필요성은 아직도 높다.

그럼 쿠키를 사용하는 방법에 대해 정리해 보자. 쿠키는 “Cookie"라는 클래스로 준비되어 있다. 이것은 다음과 같이 인스턴스를 만든다.

Cookie 변수 = new Cookie(이름, 값);

쿠키는 저장하는 값과 거기에 붙이는 이름이 세트로 되어 있다. 이렇게 하면 여러 값을 이름으로 정리하고 보관할 수 있도록 되어 있다. 그럼 이 쿠키는 어떻게 저장하고 검색할 수 있을까?

쿠키 저장하기

response.addCookie("Cookie");

쿠키 받아오기

Cookie[] 변수 = request.getCookies();

쿠키의 저장은 “response"라는 객체의 메소드를 호출한다. 이는 클라이언트에 대한 응답에 대한 정보를 관리하는 객체이다. 이 “addCookie” 메소드로 저장하는 Cookie 인스턴스를 인수로 지정하여 실행한다.

쿠키를 받아오기는 조금 귀찮다. JSP 기능에는 특정 쿠키만 얻어오는 기능은 없다. 준비되어 있는 것은 객체 request의 “getCookies"라는 메소드뿐이다. 이는 해당 사이트에 저장되어 있는 모든 쿠키를 Cookie 배열로 얻는다. 얻어온 Cookie는 저장되어 있는 이름과 값은 다음과 같이 꺼낼 수 있다.

쿠키 이름을 얻기

String 변수 = "Cookie".getName();

쿠키 값을 얻기

String 변수 = "Cookie".getValue();

따라서 조금 복잡하지만, getCookies에서 모든 쿠키를 얻어와서 반복하여 순차적으로 Cookie를 꺼내 그 이름을 getName에서 체크하는 형태로 필요한 쿠키를 찾아야 한다.

유효 기간을 설정하기

"Cookie".setMaxAge(초);

마지막으로 또 하나, 기억해야 할 것이 이것이다. 이는 쿠키가 저장되는 기간을 설정하는 것이다. 이렇게 하면 해당 쿠키가 언제까지 저장되는지를 설정할 수 있다. 이것으로 설정을하지 않으면 브라우저를 종료하거나 하면 그 시점에서 쿠키가 사라진다.

쿠키를 사용해 본다.

그러면 실제로 쿠키를 사용하여 데이터를 클라이언트에 저장하고 그것을 꺼내는 작업을 해보기로 한다.

여기에서는 간단한 메시지를 로드 횟수를 쿠키에 저장하는 샘플을 생각해 보았다. 아래 예제가 해당 JSP 소스 코드이다.

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<%@ page import="java.net.*"%>
<%
    // 엔코딩을 설정해 둔다.
    request.setCharacterEncoding("utf-8");
    response.setCharacterEncoding("utf-8");
    req = request;
    // 입력 필드 값을 얻는다.
    String input = request.getParameter("input");
    if (input == null)
        input = "";
    // message와 count의 쿠리를 얻는다.
    Cookie msg = getCookie("message");
    Cookie count = getCookie("count");
    // msg가 null이라면 새로 쿠키를 만든다.
    if (msg == null) {
        input = URLEncoder.encode(input, "utf-8");
        msg = new Cookie("message", input);
        response.addCookie(msg);
    }
    // count가 null이라면 새로 쿠키를 만든다.
    if (count == null) {
        count = new Cookie("count", "0");
        response.addCookie(count);
    } else { // null이 아니라면 count의 숫자를 1을 올려서 설정한다.
        String num = count.getValue();
        int n = Integer.parseInt(num);
        n++;
        count = new Cookie("count", String.valueOf(n));
        response.addCookie(count);
    }
    // 입력 필드에 뭔가 적혀 있다면 쿠키를 새로 설정하여 고친다.
    if (!input.equals("")) {
        input = URLEncoder.encode(input, "utf-8");
        msg = new Cookie("message", input);
        response.addCookie(msg);
        count = new Cookie("count", "1");
        response.addCookie(count);
    }
%>
<%!HttpServletRequest req;

    // 지정한 이름의 쿠키를 얻어 오는 메소드 정의
    Cookie getCookie(String s) {
        Cookie[] cookies = req.getCookies();
        Cookie res = null;
        if (cookies != null) {
            for (Cookie c : cookies) {
                if (s.equals(c.getName())) {
                    res = c;
                    break;
                }
            }
        }
        return res;
    }%>
<!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>
    <p><%=count.getValue() + ": " + URLDecoder.decode(msg.getValue(), "utf-8")%></p>
    <form method="post" action="hello8.jsp">
        <table>
            <tr>
                <td>입력</td>
                <td><input type="text" id="input" name="input"></td>
            </tr>
            <tr>
                <td></td>
                <td><input type="submit" value="송신"></td>
            </tr>
        </table>
    </form>
</body>
</html>

이 JSP 페이지에 액세스하면 입력 필드가 하나의 양식이 나타난다. 여기에 텍스트를 써서 보내면, 그 메시지가 쿠키에 저장되어 액세스할 때 페이지에 표시된다. 여러번 다시 로드해 보면, 보낸 메시지를 제대로 기억되어 페이지에 표시되는 것을 알 수 있다.

또한 새로 고침할 때마다 카운터의 수가 증가한다. 마지막 카운터 수가 쿠키에 저장되어 있으며, 거기에 1 더한 값을 쿠키에 저장하고 다시 값을 업데이트 하도록 되어 있다. 이는 메시지를 전송하여 변경하면 초기화되고 처음부터 다시 카운트한다.

여기에 이름을 지정하고 Cookie를 가져 오는데 getCookie라는 메소드를 정의해 두었다. 이 메소드는 getCookies에서 모든 Cookie의 배열을 가져온다. 반복을 하여 이름을 확인하고 있다. 여기에서 주의해야 하는 것은 “암시 개체(HttpServletRequest)“를 다루는 것이다.

이 getCookie 메소드는 req.getCookies();으로 Cookie 배열을 얻고 있지만,이 req는 암시 개체가 아니다. 사실은 이런 메소드 정의에서 암시 객체는 사용할 수 없다. 암시 객체는 <% %>에 작성된 코드(일반적으로 “스크립트"라고 한다) 내에서만 사용할 수 있다. 따라서 여기에서는 미리 글로벌 변수를 준비해 두어 이에 request를 할당하여 사용하고 있다.

또 다른 하나의 주의할 점은 “쿠키에 저장 텍스트"에 대해서 이다. 쿠키에 저장할 수 있는 것은 일반 아스키 텍스트(영숫자)뿐이다. 한글 등은 그대로 보관 할 수 없다.

그러 한글은 어떻게 보관해야 하나? 이는 “아스키 텍스트로 표현할 수 있는 형태로 인코딩하는"것이다. “URL 인코딩"라는 것으로, 이 형식으로 텍스트를 변환하여 저장하고 꺼낸 다시 디코딩하여 텍스트를 되돌린다.

텍스트를 URL 인코딩

String 변수 = URLEncoder.encode(값, 인코딩 이름);

텍스트를 URL 디코딩

String 변수 = URLDecoder.decode(값, 인코딩 이름);

URLEncoder.encode는 텍스트를 URL 인코딩한 것을 돌려준다. 그리고 URLDecoder.decode는 인코딩된 텍스트를 원본 텍스트에 되돌린 것을 돌려준다. 이것을 이용하여 텍스트를 인코딩하여 쿠키에 저장하고, 쿠키에서 꺼낸 후 다시 디코딩하여 사용하는 방식으로, 한글도 문제없이 쿠키에 보관할 수 있다.

이 밖에 요청과 응답에 각각의 텍스트 인코딩을 설정하는데 다음과 같은 문장을 처음에 실행하고 있다.

request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");

인코딩을 제대로 설정해 두는 것으로, 한글의 문자 깨짐 등을 예방하는데 도움이 된다. 이전 폼의 전송 등의 경우에는 하지 않았지만, 한글을 사용하는 경우 이러한 설정을 해두는 편이 좋다. 여기서는 이를 기억해 두도록 하자.