Home [Web] 쿠키와 세션
Post
Cancel

[Web] 쿠키와 세션

HTTP는 Connectionless, Stateless 하다는 특징이 있습니다.

  • Connectionless는 클라이언트가 요청을 한 후 응답을 받으면 연결을 끊어버린다.
  • Stateless는 클라이언트의 상태 정보를 가지지 않는다. 클라이언트와 첫 번째 통신에서 데이터를 주고받았다 해도, 다음에 이전 데이터를 유지하지 않는다.

우리가 페이지를 이동하더라도 로그인 상태를 유지하거나, 장바구니에 넣은 목록을 유지하는 등 데이터를 유지할 필요가 있습니다. 이 때 HTTP의 Connectionless, Stateless한 점을 보완하여 클라이언트가 누군지 확인하고, 데이터를 유지하기 위해 쿠키와 세션을 사용합니다.

쿠키와 세션에 대해서 알아보고, JSP에서 어떻게 사용하는지 알아보겠습니다.

쿠키

웹 브라우저가 보관하는 데이터

  • 웹 서버와 웹 브라우저 양쪽에서 생성할 수 있다.

쿠키 동작 방식

  1. 쿠키 생성 단계 : JSP 쿠키는 웹 서버 측에서 생성한다. 생성한 쿠키를 응답 데이터의 헤더에 저장해서 웹 브라우저에 전송한다.
  2. 쿠키 저장 단계 : 웹 브라우저는 응답 데이터에 포함된 쿠키를 쿠키 저장소에 보관한다. 쿠키의 종류에 따라 메모리나 파일에 저장한다.
  3. 쿠키 전송 단계 : 웹 브라우저는 매번 저장된 쿠키를 Header에 포함해서 요청을 보낸다. 웹 서버는 쿠키를 사용해서 필요한 작업을 수행한다.

쿠키 구성 요소

  • 이름 : 각각의 쿠키를 구별하는데 사용하는 이름
  • 값 : 쿠키의 이름과 관련된 값
  • 유효시간 : 쿠키의 유지시간
  • 도메인 : 쿠키를 전송할 도메인
  • 경로 : 쿠키를 전송할 요청 경로

이름은 보통 알파벳과 숫자만 사용한다. 유효시간 뒤에 쿠키가 삭제되고, 유효시간이 지정되어있지 않을 경우 웹 브라우저를 종료할 때 삭제된다. 지정한 도메인이나 경로로만 전송하도록 제한할 수 있다.

쿠키 생성하기

Cookie 클래스 사용

1
2
Cookie cookie = new Cookie("cookieName", "cookieValue");
response.addCookie(cookie);
  1. 쿠키 객체 생성
  2. 쿠키 추가(웹 브라우저에 쿠키 정보를 전송한다)
    • 쿠키의 도메인과 경로는 도메인 간에 또는 특정 요청 경로에 위치한 JSP 간에 쿠키를 공유할 때 필요하다.

쿠키 값 변경

같은 이름의 쿠키를 새로 생성해서 응답 데이터로 보내면 된다.

  • 쿠키 값 존재 여부 확인 후 처리해줘도 된다.
1
2
3
4
5
6
for(int i = 0; i < cookies.length; i++) {
	if(cookies[i].getName().equals("name")) {	// "name" 쿠키 값 존재 여부 확인
		Cookie cookie = new Cookie("name", URLEncoder.encode("JSP프로그래밍", "utf-8"));
		response.addCookie(cookie);
	}
}

쿠키 삭제

유효 시간을 0으로 지정해준 뒤 응답 데이터로 보낸다.

1
2
3
Cookie cookie = new Cookie("name", "value");
cookie.setMaxAge(0);
response.addCookie(cookie);

쿠키의 도메인

  • 기본적으로 쿠키는 그 쿠키를 생성한 서버에만 전송된다. www.somehost.com 👉 www.somehost.com
  • setDomain() 사용해서 생성한 쿠키를 전송할 수 있는 도메인을 지정할 수 있다.
    • . 점으로 시작하는 경우 관련 도메인에 모두 쿠키를 전송한다. (쿠키의 범위 확장) .somehost.com 👉 www.somehost.com / mail.somehost.com / javacan.somehost.com
    • 점이 아닌 문자로 시작하는 경우 해당 도메인에만 쿠키를 전송한다. www.somehost.com 👉 www.somehost.com
    • 설정하지 않으면 그 쿠키를 생성한 해당 도메인에만 쿠키를 전송한다.
  • 도메인에 대한 예제를 테스트할 때 C:\Windows\System32\drivers\etc 폴더의 host 파일을 수정한다. 127.0.0.1 javacan.somehost.com

도메인에 따른 쿠키의 종류

  • 브라우저 쿠키
    • 기본적으로 쿠키를 보낸 서버가 속한 도메인으로만 쿠키를 되돌려 보낸다. 이런 경우 해당 URL에서만 쿠키를 사용한다.
  • 도메인 쿠키
    • Domain 파라미터를 설정하면 서브 도메인까지 쿠키를 보내서 쿠키를 공유할 수 있게 된다.
    • naver.com 으로 설정한다면 a.naver.com 또는 b.naver.com으로 보낸다.

쿠키의 경로

  • 경로는 URL에서 서버 주소 이후 부분인 디렉터리 부분이다. URL : https://localhost:8080/chap09/path2/viewCookies.jsp 경로 : /chap09/path2/viewCookies.jsp
  • 쿠키에서 사용하는 경로는 디렉터리 수준까지의 경로를 사용한다. 예 : / or /chap09 or /chap09/path2
  • setPath() 를 사용해서 쿠키의 경로를 지정할 수 있다.
    • 설정한 경로와, 하위 경로까지 전송한다. (쿠키의 범위 축소)
    • 설정하지 않으면 실행한(쿠키를 보냈던) URL의 경로 부분을 사용한다.

쿠키의 유효시간

  • 쿠키는 유효시간을 갖는다.
  • 유효시간을 지정하지 않으면 웹 브라우저를 종료할 때 쿠키를 함께 삭제한다. 웹 브라우저 종료 후 다시 웹 브라우저를 실행하면 삭제한 쿠키는 서버에 전송되지 않는다.
  • 유효시간을 지정하면 그 유효시간동안 쿠키가 존재하고, 웹 브라우저를 종료해도 유효시간이 지나지 않으면 쿠키를 삭제하지 않는다.
  • setMaxAge() 를 사용해서 유효시간을 지정한다.
    • 초 단위로 지정한다. (1시간 = 60*60)
  • 아이디 기억하기 기능을 구현할 때 쿠키를 사용한다.
    • 사용자가 로그인에 성공하면 아이디를 값으로 저장하고 있는 쿠키의 유효시간을 여유롭게 잡아서 생성한다. 그러면 다음에 웹 브라우저를 실행할 때 아이디를 저장하고 있는 쿠키를 사용할 수 있다.

유효기간에 따른 쿠키의 종류

  • 세션(Session) 쿠키
    • 브라우저를 닫으면 사라지는 쿠키(유효기간이 없다)
    • 탭으로 나뉘어져있어도 쿠키가 공유된다
  • 영속(Persistent) 쿠키
    • 브라우저를 닫아도 유효기간까지 저장되는 쿠키
    • 디스크에 저장되며 컴퓨터를 재시작해도 남아있다
    • 사용자 로그인 유지에 사용된다
  • Session 쿠키와 Persistent 쿠키의 차이점
    • Discard 파라미터가 true(디스크에 저장)이거나, Expires(종료시점), Max-age(유효기간) 파라미터가 설정되어 있으면 Persistent 쿠키이다.

쿠키와 헤더

  • response.addCookie() 로 쿠키를 추가하면 Set-Cookie 헤더를 통해 전달된다.
  • 한 개의 Set-Cookie 헤더는 한 개의 쿠키 값을 전달한다.
  • Set-Cookie 헤더의 구성 Set-Cookie: 쿠키이름=쿠키값; Domain=도메인값; Path=경로값; Expires=GMT형식의만료일시

세션

서버(웹 컨테이너)가 보관하는 데이터

  • 웹 컨테이너는 기본적으로 한 웹 브라우저마다 한 세션을 생성한다. 👉 웹 브라우저와 관련된 정보를 저장하기 알맞은 장소이다.
  • 같은 JSP 페이지어도 웹 브라우저에 따라 서로 다른 세션을 사용한다.
  • 로그인한 사용자의 정보를 유지하기 위한 목적으로 세션을 사용한다.

세션 생성하기

  • page 디렉티브의 session 속성을 true로 지정한다.
    • <%@ page session="true" %>
    • 기본값이 true이므로 session 속성값을 false로 지정하지만 않으면 세션이 생성된다.
  • 세션을 생성하면 session 기본 객체를 통해 세션을 사용할 수 있다.
  • 서버 프로그램에 웹 브라우저가 처음 접속할 때 세션을 생성하고, 이후로는 이미 생성된 세션을 사용한다.

session 기본 객체

session 기본 객체는 request 기본 객체와 마찬가지로 속성을 제공하므로 메서드를 사용하여 속성값을 저장하거나 읽어올 수 있다.

메서드

메서드설명
String getId()세션의 고유 ID(세션ID)를 구한다.
long getCreationTime()세션이 생성된 시간을 구한다.
long getLastAccessedTime()웹 브라우저가 가장 마지막에 세션에 접근한 시간을 구한다.
  • 시간을 구할 때 1970년 1월 1일 이후 흘러간 시간을 의미하고, 단위를 1/1000초로 가져온다. 이를 보기 편하게 출력하기 위해 아래와 같은 방법을 사용한다.
1
2
3
4
Date time = new Date();
SimpleDateFormat formatter = new SImpleDateFormat("yyyy-MM-dd HH:mm:ss");
time.setTime(session.getCreateTime());
formatter.format(time);
  • 웹 브라우저마다 별도의 세션을 구분하기 위해 각 세션마다 할당하는 고유 ID를 세션 ID라고 한다.
    • 웹 서버가 웹 브라우저에 세션 ID를 전송한다.
    • 웹 브라우저는 웹 서버에 연결할 때마다 매번 세션 ID를 보내서 웹 서버가 어떤 세션을 사용할지 판단할 수 있게 한다.
    • 웹 서버와 웹 브라우저는 세션ID를 공유하기 위해 쿠키를 사용한다. (JSESSIONID 쿠키를 이때 사용한다.)

속성 사용

로그인한 회원 정보 등 웹 브라우저와 일대일로 관련된 값을 저장할 때 쿠키 대신 세션을 사용할 수 있다.

  • 중요한 데이터를 저장할 때 알맞은 장소이다.
  • 쿠키를 지원하지 않을 경우 사용할 수 있다.
  • 여러 서버에서 공유할 수 없다.

setAttribute() 를 사용해서 속성에 값을 저장한다.

1
session.setAttribute("NAME", "김소연");

getAttribute() 를 사용해서 속성값을 읽는다.

1
String name = (String)session.getAttribute("NAME");

세션 종료

session.invalidate() 를 사용해서 세션을 종료한다.

  • 현재 사용 중인 session 기본 객체를 삭제하고, 저장했던 속성 목록도 함께 삭제한다.
  • 세션 종료 후 다음 요청에서 session을 사용하면 새로운 session 기본 객체를 생성한다.

세션 유효시간

세션은 최근 접근 시간을 갖는다.

  • 세션을 사용하도록 설정된 JSP 페이지에 접근할 때마다 세션의 최근 접근 시간을 변경한다.
  • 세션은 마지막 접근 이후 일정 시간 이내에 다시 세션에 접근하지 않는 경우 자동으로 세션을 종료하는 기능을 갖고 있다. (이후 세션을 요청하면 새로운 세션 생성)

세션 유효시간 설정하는 두가지 방법

  1. WEB-INF\web.xml 파일에 <session-config> 태그를 사용하여 세션 유효 시간을 지정한다. (값의 단위는 분이다.)
    • 0이나 음수로 설정할 경우 유효시간을 갖지 않는다.
    • invalidate() 호출 전까지 세션 객체가 유지된다. 세션 객체가 메모리에 남게되어 메모리 부족 현상이 발생하게 된다. 👉 반드시 세션 타임아웃 시간을 지정해주어야 한다.
1
2
3
<session-config>
	<session-timeout>50</session-timeout>
</session-config>  
  1. session 기본 객체의 setMaxInactiveInterval() 메소드를 사용한다. (값의 단위는 초다.)
1
session.setMaxInactiveInterval(60*60);

request.getSession() 을 사용한 세션 생성

request.getSession() 은 현재 요청과 관련된 session 객체를 리턴한다.

  • page 디렉티브의 session 속성값은 false로 지정한다.
  • session이 이미 존재하면 해당 session을 리턴하고, 존재하지 않으면 새롭게 session을 생성해서 리턴한다.
  • false 인자를 전달하면 새롭게 생성된 경우에만 session 객체를 리턴한다. (아니면 null 리턴)

세션을 사용한 로그인 상태 유지

  1. 로그인에 성공하면 session 기본 객체의 특정 속성에 데이터를 기록한다.
  2. 이후로 session 기본 객체의 특정 속성이 존재하면 로그인한 것으로 간주한다.
  3. 로그아웃할 경우 session.invalidate() 메소드를 호출하여 세션을 종료한다.

쿠키와 세션 비교

쿠키세션
- 웹 브라우저에 보관한다
- 클라이언트의 로컬에 저장되기 때문에 보안에 취약하다.
- 만료 시간이 있지만 파일로 저장되기 때문에 브라우저를 종료해도 계속해서 정보가 남아있을 수 있다.
- 세션보다 더 빠르다.
- 서버에 보관한다
- 쿠키를 이용해서 sessionid만 저장하고 그것으로 구분해서 서버에서 처리하기 때문에 비교적 보안성이 좋다.
- 만료 시간이 있지만 브라우저가 종료되면 만료시간에 상관없이 삭제된다.
- 쿠키보다 더 느리다. 서버의 처리가 필요하기 때문이다.

세션을 사용하면 좋은데 쿠키를 사용하는 이유

세션은 서버에 보관되기 때문에 무분별하게 만들다보면 서버의 메모리가 감당할 수 없어지고 속도가 느려질 수 있기 때문이다.

쿠키의 한계

유실되기 쉽다

대부분 브라우저는 환경 설정에서 쿠키 일괄 삭제 기능을 제공하며, 웹사이트 별로도 어렵지 않게 쿠키를 삭제할 수 있다.

변조되기 쉽다

브라우저의 개발자 도구를 사용하면 각 웹사이트 별로 현재 어떤 쿠키가 저장되어 있는지 한 눈에 파악할 수 있으며 쿠키를 손쉽게 변경할 수 있다.

도난되기 쉽다

클라이언트에 저장되어 있는 쿠키가 탈취되는 것을 서버 입장에서 막을 수 없다.

쿠키의 대체기술

  • 대부분의 모던 브라우저는 로컬 스토리지나 세션 스토리지와 같은 쿠키를 대체할 수 있는 웹 스토리지 기술을 지원하고 있다.
  • 웹 개발의 패러다임이 백엔드에서 프런트앤드로 옮겨오면서 예전보다 많은 코드가 서버가 아닌 브라우저에서 실행되고 있습니다. 그래서 굳이 브라우저에 저장되어 있는 데이터를 서버로 전송하지 않고도 자바스크립트로 해당 데이터에 쉽게 접근할 수 있게 되었다.

이러한 웹 스토리지 기술에 비해서 쿠키의 최대 단점은 매 요청마다 같은 데이터가 서버로 전송됨에 따른 네트워크 대역폭 낭비이다.

쿠키를 사용할 수 밖에 없는 이유

이처럼 쿠키는 단점이 많지만 사용할 수 밖에 없는 이유는 HTTP 프로토콜은 연결을 유지시키지 않고(connectionless) 상태가 없는(stateless) 특성 때문이다.

쿠키를 사용하여 서버로 유입되는 요청 중에서 각각 어떤 사용자의 요청인지 판단할 수 있다.

1. 대규모 서비스에서 부하 분산

사용자들로부터 많은 요청이 들어올 때 여러 대의 서버를 사용하고, 이러한 서버 앞에는 로드 밸런서를 두어 여러 대의 서버로 부하가 분산될 수 있도록 한다. 만약 로그인한 서버와 다음 요청을 한 서버가 다르다면 그 서버에는 세션정보가 존재하지 않기 때문에 로그인 상태를 유지하기 어렵다. 이 때 서버의 ID를 쿠키로 지정하면, 로드밸런서는 이 서버 식별자를 보고 항상 동일한 서버로 요청을 보내줄 수 있다.

2. 세션 기반 사용자 인증

서버에서 세션을 생성하면 그 세션을 식별할 수 있는 식별자 (세션 ID)를 얻는다. 이 세션ID를 쿠키로 설정하면 브라우저는 요청을 보낼 때마다 세션ID를 포함한 쿠키를 서버로 돌려보낸다. 서버에서는 이 세션ID에 해당하는 세션이 있는지 확인하면 된다.

악용되는 쿠키

서드파티(Third party) 쿠키

  • 브라우저로 웹사이트에 접속할 때 그 웹사이트의 도메인이 아닌 타 도메인을 상대로 적용되는 쿠키이다.
  • 보통 사용자 맞춤 광고를 위해서 사용자가 어떤 웹사이트를 방문하는지 추척하는 용도로 많이 사용이 되고 있다.

캐시란?

캐시는 쿠키와 세션과 다르다.

이미지, css, js 파일 등 리소스 파일들을 사용자의 PC에 저장해놓고 로드하게 해서 서버를 거치지 않아도 된다. 다시 사용할 때 빠르게 접근할 수 있어서 페이지 로딩 속도를 개선할 수 있다.

한 번 캐시에 저장되면 브라우저를 참고하기 때문에 서버에서 변경이 되어도 사용자는 변경되지 않게 보일 수 있다. 이 때 캐시를 직접 지워주거나, 서버에서 클라이언트로 응답을 보낼 때 header에 캐시 만료시간을 명시하는 방법 등이 있다.

출처

  • 최범균의 JSP 2.3 웹 프로그래밍
  • https://interconnection.tistory.com/74
  • https://www.daleseo.com/http-cookies/
This post is licensed under CC BY 4.0 by the author.