JSP & Servlet - cookie(쿠키)

|

개인적인 연습 내용을 정리한 글입니다.
더 좋은 방법이 있거나, 잘못된 부분이 있으면 편하게 의견 주세요. :)


우리가 일상생활에서 쿠키를 먹다보면 과자 부스러기(흔적)을 남기듯이 컴퓨터 프로그램에서도 흔적을 남긴다는 것을 쿠키라고 한다. 서버에 클라이언트가 연결을 시도한 흔적을 쿠키라고 하며 나중에 서버에 재 접속할 때 그 흔적을 통해 앞으로의 접속은 이어나가자 라는 의미로 사용된다.

우리가 현재 사용하고 있는 프로토콜은 http인데, 이 http의 특징은 아래와 같다.

  • 클라이언트는 브라우저를 통해 서버에게 어떤 데이터를 어떻게 달라는 요청(request)를 한다.
  • 서버는 웹 서블릿과 jsp, 혹은 데이터베이스와 연동해 데이터 작업을 한다.
  • 데이터 작업이 완료되면 서버는 클라이언트에 해당 작업에 대한 응답(response)를 한다.
  • http 프로토콜은 한번의 요청과 응답이 완료되면 해당 클라이언트와 서버와의 연결도 바로 해제시킨다.
  • 즉, 같은 클라이언트가 서버에게 또 요청하기 위해서는 새로운 연결이 필요하다는 의미이다.

이렇게 한번의 요청과 한번의 응답 후 연결이 해제되는 이유는 하나의 서버에는 수많은 클라이언트들이 연결되어있기에 이 모든 클라이언트들의 연결을 계속해서 유지시킨다면 서버의 부하가 과다해지기 때문이다. 즉, 한번 요청이 가고 응답이 오면 순간적으로 이 연결을 바로 해제시키게 된다.

이렇듯 자원을 낭비하지 않기위해 서버는 연결을 해제시키는데, 우리가 인터넷 쇼핑을 한다고 생각해보자.

나는 인터넷 쇼핑몰을 통해 장바구니에 쇼핑하고싶은 제품들을 넣게되는데, 한번 요청하고 응답할때마다 그 연결이 끊긴다고 한다면 결국 내 장바구니에 최종적으로 담겨있는 물건은 마지막에 내가 장바구니에 담은 상품일 것이고 그 마저도 내가 다음 요청을 하게된다면 아무것도 남아있는것이 없을 것이다.

혹은, 내가 로그인을 할때에도 내 로그인 정보를 유지시키고 싶은데, 내가 다른 브라우저 창으로 가게된다면 그 즉시 나의 로그인 기록은 사라지게 될 것이다.

이렇게 나는 어떤 특정 데이터들은 일정시간동안 유지되기를 바라는데, 일반적인 http 프로토콜에는 이같은 과정이 존재하기 힘든것이고 그렇기 때문에 우리는 쿠키를 통해 서버와 클라이언트(브라우저)간의 데이터를 연결해주는 고리로 사용하게 되었다.

쿠키는 브라우저에 연결정보(처음 요청하고 서버가 응답을 한 정보)를 서버에 저장하기에는 부하가 걸릴 수 있으니 해당 브라우저 클라이언트에 기존 연결정보를 저장하는 방식이다.

쿠키 구현해보기

  • 어떤 클라이언트가 서버에 요청을 했을 경우 쿠키가 null값인지를 확인해본다.
  • 쿠키가 null이라면 해당 페이지에 처음 접속한 것으로 쿠키를 새롭게 생성해준다.
  • 만약 쿠키가 null이 아니라면 과거 연결정보를 통해 쿠키를 재활용하도록 한다.

  • 이러한 쿠키는 하나의 데이터만 존재하는게 아닐 수 있으니 배열로 관리한다.
  • 쿠키는 항상 클라이언트쪽에 정보가 있기때문에 request객체에 들어갈 수 있다.
    • requst객체로부터 getCookie()한다.

login.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>loginOK</title>
</head>
<body>

<form action="loginCon" method="post">
  ID: <input type="text" name="mID">
  PW: <input type="password" name="mPW">
  <input type="submit" value="login">
</form>

</body>
</html>

loginCon.java

  • 유저가 폼으로부터 입력한 파라미터(아이디, 패스워드)를 받아서 쿠키에 저장
  • for문을 통해 가져온 쿠키들을 조회
  • 과거 접속이력이 있다면 cookie에 저장
  • 과거 접속 이력이 없다면 cookie에 새로 저장
  • 응답할때는 response객체를 통해 addCookie해준다.
  • setMaxAge()를 통해 쿠키의 유지 시간을 설정해준다.(60초)
package com.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

public class LoginCon extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        PrintWriter out = response.getWriter();
        String mID = request.getParameter("mID");
        String mPW = request.getParameter("mPW");
        out.print(mID);
        out.print(mPW);

        Cookie[] cookies = request.getCookie();
        Cookie cookie = null;

        for(Cookie c: cookies){
          System.out.println(c.getName() + c.getValue());
          if(c.getName().equals("memberID")){
            cookie=c;
          }
        }

        if(cookie == null){
          System.out.println("Cookie is null!");
          cookie = new Cookie("memberID", mID);
        }

        response.addCookie(cookie);
        cookie.setMaxAge(60*60);

        response.sendRedirect("loginOK.jsp")
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

    }
}

loginOK.jsp

  • 쿠키가 잘 왔는지 확인
<%@ page language="java" contentType="text/html; charset=EUC-KR"
   pageEncoding="EUC-KR"%>
<!DOCTYPE html>
<html>
<head>
  <meta charset="EUC-KR">
  <title>Insert title here</title>
</head>
<body>

<%
  Cookie[] cookies = request.getCookie();
  for (Cookie c: cookies){
    out.print(c.getName() + c.getValue());
  }
%>

</body>
</html>

login.jsp

  • 추가로 이미 로그인이 되어있던 상태라면 다시 이 페이지가 보이면 안된다.
  • 즉, 이미 로그인했던 쿠키가 존재한다면 이미 로그인이 되어있기에 해당 폼으로의 이동은 안된다.
  • request.getCookie()를 통해 모든 쿠키를 가져오고
  • cookies가 null이 아니라면 cookies를 for문을 통해 조회 후
  • memberID가 존재한다면 login 폼이 아닌 loginOK 폼으로 돌아가게 설정
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>loginOK</title>
</head>
<body>
  <%
    Cookie cookies = request.getCookie[];
    System.out.println("cookies:" + cookies);

    if (cookies != null) {
      for(Cookie c:cookies) {
        if(c.getName().equals("memberID")){
          response.sendRedirect("loginOK.jsp");
        }
      }
    }
  %>

<form action="loginCon" method="post">
  ID: <input type="text" name="mID">
  PW: <input type="password" name="mPW">
  <input type="submit" value="login">
</form>

</body>
</html>

실제 로그를 살펴보면 과거 접속이 없었음에도 불구하고 쿠키가 1개 존재하는것으로 나온다.

이는 memberID 쿠키가 아닌 브라우저가 만든 자체적인 쿠키이다. 즉, 실제 로그인을 해보면 방금 로그인하면서 만들어진 쿠키와 브라우저가 만든 쿠키의 로그가 생긴다.

쿠키는 자주 쓰이지만 보안에 취약하다는 단점이 존재한다. 왜냐면 사용자의 정보가 본인의 pc(브라우저)에 저장되는 것으로 중요한 정보가 나중에 유출될 위험이 있다는 것을 의미한다. 따라서 쿠키에 저장하는 데이터는 굉장히 중요하거나 위험한 정보를 저장하기 보다는 간단한 데이터 정도를 저장하는 것을 선호한다.