Cookie
쿠키란?
“내가 만든 쿠키~”
HTTP 프로토콜은 상태가 없다. 상태를 기억하지 않는다.
즉, 한 명의 사용자가 요청을 연달아 보내도 모두 별개의 요청으로 인식된다. 이는 적은 자원으로 여러 건의 요청을 처리할 수 있게하기 위함이다.
가만 생각해보면 쇼핑을 할 때 최근 본 상품이라던가 로그인 상태가 지속된다던가 하는 걸 많이 봐왔다. HTTP프로토콜은 요청을 기억하지 않는데 이게 어떻게 가능한건지 궁금할 수 있다.
이러한 기법을 세션 트랙킹이라고 부른다.
세션 트래킹은 유저의 경험인 UX에 큰 편리함을 준다. 쇼핑을 할 때 여러가지 비슷한 상품을 보고 비교해보고 하나를 사곤 한다. 그럴 때마다 메모를 해두거나 즐겨찾기를 해야한다면 무척이나 귀찮을 것이다. 그리 웹 서비스를 이용하며 다른 페이지로 넘어갈 때마다 매번 로그인을 해야한다면 불편해서 서비스를 이용하기 싫어질 것이다.
그래서 이전의 요청을 기억하게 해서 웹 서비스를 더 재미있고 편리하게 만드는 방법을 생각해내게 되는데 그게 바로 세션 트랙킹 기법이다.
세션 트랙킹은 쿠키와 세션을 이용하는데 쿠키라는 단어는 우리가 생각하는 그 쿠키가 맞을 것이다. 작은 정보 뭉치로 이루어져있고 상태를 기록한다는 점에서 개발자 나름의 센스가 아니였을까 싶다.
쿠키는 키와 값으로 구성되는 작은 정보의 뭉치로 클라이언트에 저장된다. 직접 확인해보고싶다면 브라우저에서 개발자 도구를 연다음 애플리케이션 탭을 보면 쿠키를 확인할 수 있다. 하나씩 삭제해보고 어떤게 달라지는지 확인해봐도 재미있을 것이다.
쿠키의 특징
- 쿠키는 서버에서 클라이언트로 전송되어 사용자의 컴퓨터에 저장한다. 그리고 저장된 쿠키는 웹 페이지에 요청을 보낼 때 서버에 같이 전송된다.
- 쿠키는 이름과 값으로 이루어져있고 이 외에도 도메인, 경로, 유효기간, 보안, HttpOnly와 같은 속성을 지정할 수 있다. 따라서 어떤 특정 경로에 요청을 보낼 때 쿠키에 설정된 경로와 같다면 요청시 같이 전송된다.
- 쿠키의 이름은 일반적으로 알파벳과 숫자, 언더바로 구성한다.
- 하나의 쿠키는 4키로바이트로 제한되고 브라우저는 각각의 웹사이트당 20개의 제한을 두고있다. 모든 웹사이트를 합쳐서 최대 300개를 허용한다. 그러니 2.2mb까지의 쿠키를 저장할 수 있다.
쿠키 사용하기
자바에서 쿠키를 다루는 패키지는 javax.servlet.http.Cookie
로 서버에서 쿠키를 생성하고, Reponse의 addCookie메소드를 이용해 클라이언트에게 전송하는 방식으로 동작한다.
예를 들어 서버에서 쿠키를 발행하고 싶다면 다음과 같이 코드를 짜면 된다.
Cookie cookie = new Cookie(이름, 값);
response.addCookie(cookie);
다음은 클라이언트가 보낸 쿠키 정보를 읽는 방법이다.
Cookie[] cookies = request.getCookies();
위의 코드에서 쿠키 값이 없으면 null이 반환되고 Cookie가 가지고 있는 getName()과 getValue()메소드를 이용해서 원하는 쿠키정보를 찾아 사용한다.
서버에서 클라이언트에서 보관하고있는 쿠키를 삭제시키고 싶을 수 있다.
쿠키를 삭제하는 명령은 없고, 쿠키에 유효 기간을 설정할 수 있다는 점을 활용하여 maxAge가 0인 같은 이름의 쿠키를 전송하면 된다.
Cookie cookie = new Cookie("이름", null);
cookie.setMaxAge(0);
response.addCookie(cookie);
여기서 쿠키는 중복을 허용하지 않는다는 사실을 알 수 있다.
쿠키에 유효기간을 설정할 땐 setMaxAge()
메소드를 사용한다.
메소드의 인자는 유효기간을 나타내는 초 단위의 정수형이다.
예를 들어 쿠키가 10분 후에 만료되도록 설정하려면 10 * 60를 인자로 놓어주면 된다. 만약 1주일로 정하고 싶다면 7 * 24 * 60 * 60으로 설정하면 된다.
위에서 살펴본대로 유효기간을 0으로 지정하면 쿠키가 삭제되고 음수를 지정하면 브라우저가 종료될 때 쿠키가 삭제된다.
쿠키의 종류
쿠키는 크게 두 가지 종류가 있다.
- 세션 쿠키
- 지속 쿠키
세션 쿠키는 개발자가 작성하여 제공하는 쿠키가 아니라 WAS가 생성하는 쿠키로 개발자가 생성하는 쿠키와 구분하기 위해 세션 쿠키라는 명칭을 사용한다.
WAS에서 생성하는 쿠키의 이름은 어떤 웹 서버를 사용하느냐에 따라 달라지는데 예를 들어 톰캣에서 발행하는 세션 쿠키의 이름은 JSESSIONID이고 장고는 SESSIONID, node.js는 connect.sid를 사용한다고 한다.
세션 쿠키는 서버로부터 경로가 /
로 설정되어 전달되고 브라우저의 메모리에 저장된다. 따라서 사용자가 브라우저를 종료할 때 삭제된다.
지속 쿠키는 개발자가 생성하는 쿠키로 위에서 살펴본 대로 이름을 지정하여 발행할 수 있고 유효기간을 지정할 수 있다. 그리고 경로나 도메인을 지정하여 사용하곤한다.
쿠키를 주고받는 시나리오
- 브라우저에서 서버를 호출할 때 해당 서버에서 발행한 쿠키가 없다면 브라우저는 아무것도 전송하지 않는다.
- 서버에서 응답 메시지를 보낼 때 쿠키를 포함해서 전달한다. 이 때 Set-Cookie라는 HTTP헤더를 사용한다.
- 브라우저는 쿠키를 받은 뒤 쿠키에 담긴 정보를 통해 파일 형태로 보관할지 메모리에서 보관할지를 결정한다.
- 브라우저가 보관하는 쿠키는 다음에 서버에 요청할 때 HTTP 헤더에 Cookie라는 헤더와 함께 전달한다.
동작 방식
톰캣의 경우 하나의 톰캣이 여러 개의 웹 애플리케이션을 실행할 수 있다. 그리고 이렇게 실행되고 있는 각각의 애플리케이션은 고유한 메모리 영역을 생성하고 이 공간에 Servlet과 같은 인스턴스를 만들어 서비스를 제공한다.
그리고 각 웹 애플리케이션을 생성할 때 세션쿠키를 관리하기 위한 메모리 영역이 하나 더 생성되는데 이 공간을 세션 저장소라고 한다.
스프링 프로젝트를 하나 띄워서 세션 쿠키를 확인해보면 JSESSIONID
라는 이름과 알 수 없는 값을 가지는 쿠키가 존재하는 것을 확인할 수 있다.
서버에서는 이 값을 키로 보관한다. 그리고 세션 저장소에서 이 값마다 고유한 공간을 가지는데 이 공간은 다시 키와 값으로 데이터를 보관한다.
예를 들어 두 대의 브라우저가 요청을 보냈고 세션 쿠키의 값으로 AAAA1111
, BBBB2222
문자가 들어있다고 해보자. 이 문자가 세션 저장소에서 키가 된다.
이 공간에 원하는 객체들을 보관할 수 있다. 로그인 처리를 하고싶다면 이 공간에 로그인 정보를 담으면 된다.
브라우저
JSESSIONID
: AAAA1111
세션 저장소
AAAA1111
-> loginInfo 객체
, 기타 객체
이 고유한 공간에 자바의 Object를 상속받은 모든 객체를 저장할 수 있다.
그리고 자바에서는 HttpServletRequest
의 getSession()
메소드를 통해 JSESSIONID의 공간에 접근할 수 있다.
코드로 나타내보면 이렇다.
// 세션 쿠키의 값을 이용해서 세션 저장소에 접근한다.
HttpSession session = request.getSession();
session.setAttribute("loginInfo", loginInfo);
- 세션은 서버에서 보관하고 관리한다. 따라서 쿠키가 만들어질때마다 메모리 공간을 사용해야한다. 그럼 서버쪽에 부담이 갈 수 있기 때문에 웹 서버는 주기적으로 세션 저장소를 검사하여 더 이상 사용하지 않는 값을 정리한다. 톰캣의 경우 기본 30분으로 session-timeout을 설정하고 있고 서버에 접속한 후 서버에 요청을 하지 않는 최대 시간이다. 즉, 30분 이상 서버에 요청을 보내지 않으면 세션이 자동으로 끊어진다.
Spring에서 쿠키 사용법
Spring에서 쿠키를 사용하려면 @CookieValue 애노테이션을 사용하면 된다.
컨트롤러 메소드의 파라미터에서 CookieValue애노테이션을 사용함으로써 원하는 쿠키정보를 파라미터 변수에 담아 사용할 수 있다.
public String (@CookieValue(value="쿠키이름", required=false, defaultValue="기본값") String 변수명) {
// 로직
}