배고플 땐, 쿠키
서버와 클라이언트 간의 상태를 관리하는 쿠키는 HTTP/1.1의 사양인 RFC2616에 포함된 것은 아니지만 웹 사이트에서 널리 사용되고 있습니다. 쿠키는 유저 식별과 상태 관리에 사용되고 있는 기능입니다. 웹 사이트가 유저의 상태를 관리하기 위해서 웹 브라우저 경유로 유저의 컴퓨터 상에 일시적으로 데이터를 기록해 두고, 다음에 그 유저가 웹 사이트에 액세스 해 왔을 때 지난번에 발행한 쿠키를 송신받을 수 있습니다.
쿠키가 호출되었을 때는 쿠키의 유효 기한과 송신지의 도메인, 경로, 프로토콜 등을 체크하는 것이 가능하기 때문에 적절하게 발행된 쿠키는 다른 웹 사이트와 공격자의 공격에 의해 데이터가 도난당하는 일은 없습니다.
일반적으로 사용자 컴퓨터에 기록되는 두 가지 유형의 쿠키가 있습니다.
세션 쿠키 (session cookie)
- 이 쿠키는 쿠키를 트리거하는 브라우저가 열릴 때까지 활성화됩니다. 브라우저를 닫으면 이 세션 쿠키가 삭제됩니다.
- 메모리에 저장되며 디스크에는 절대 저장되지 않는다.
영구 쿠키 (permanent cookie / persistent cookie)
- 이 쿠키는 사용자 시스템에 영구적으로 기록되며 몇 달 또는 몇 년 동안 지속됩니다.
- 구글의 개발자 도구에서 쿠키를 조회하여 세션 쿠키와 영구 쿠키를 구분할 수 있는데 session cookie는 expires 컬럼에 'Session'이라는 값이 저장되어 있으며 영구 쿠키는 날짜가 기입되어 있다.
- 영구 쿠키는 이 Expires에 저장된 날짜 값이 지나면 파기된다.
세션은 클라이언트를 구분하기 위해 세션 ID를 부여하여 웹 브라우저가 서버에 접속해서 브라우저를 종료할 때까지 인증 상태를 유지하며 접속 시간에 제한을 두어 일정 시간 응답이 없다면 정보가 유지되지 않게 설정이 가능하다. 사용자에 대한 정보를 서버에 두어 쿠키보다 보안에 좋지만, 사용자가 많아질수록 서버 메모리를 많이 차지하게 된다는 단점도 존재한다. 동시접속자 수가 많은 웹 사이트의 경우 서버에 과부하를 주어 성능 저하의 요인이 되기도 한다. 또한 세션은 정보가 서버에 있기 때문에 처리가 요구되어 쿠키보다 느린 속도를 갖는다.
Session 동작 원리
- 클라이언트가 서버에 접속 시 세션 ID를 발급받는다.
- 클라이언트는 세션 ID에 대해 쿠키를 사용해 브라우저에 저장한다.
- 클라이언트는 서버에 요청할 때, 이 쿠키의 세션 ID를 같이 서버에 전달해서 요청한다.
- 서버는 세션 ID를 전달받아 세션 ID로 세션에 있는 클라이언트 정보를 가져와서 사용한다.
- 클라이언트 정보로 서버 요청을 처리하며 클라이언트에 응답한다.
Cookie 동작 원리
- 클라이언트가 서버에 HTTP 요청
- 서버가 HTTP 응답시 set-cookie를 통해 쿠키를 생성하여 전달
- 클라이언트는 이제부터 매 HTTP Request시 HTTP Header에 쿠키를 담아서 전송
- 만료 전이라면 쿠키는 브라우저에 저장되어 있으며 HTTP 요청시마다 사용 가능
- 만료되었다면 클라이언트가 서버에 새로 요청하여 쿠키를 새로 발급
Set-Cookie
Set-Cookie: status-enable; expires=Tue, 05 Jul 2011 07:26:31 GMT; ⇒path=/;domain=.hack.jp;
- 상태 관리 개시를 위한 쿠키 정보
- HTTP 응답 헤더에 포함 (Server to Client)
NAME=VAULE
- 쿠키에 부여된 이름과 값 (필수)
Expires=DATE
- 쿠키 유효 기한 (지정되지 않은 경우는 브라우저를 닫을 때까지)
쿠키의 Expires 속성은 브라우저가 쿠키를 송출할 수 있는 유효 기한을 지정할 수 있습니다. Expires 속성을 생략한 경우에는 브라우저 세션이 유지되고 있는 동안만 유효하게 됩니다. 이것은 통상 브라우저 애플리케이션을 닫을 때까지 입니다. 또한, 한번 서버에 송출한 클라이언트의 쿠키는 서버에서 명시적으로 삭제하는 방법은 없습니다. 유효 기한이 지났다면 쿠키를 덮어 쓰는 것으로 실질적인 클라이언트 측의 쿠키를 삭제하는 것이 가능합니다.
Path=PATH
- 쿠키 적용 대상이 되는 서버 상의 디렉토리 (지정하지 않은 경우는 도큐먼트와 같은 디렉토리)
쿠키의 path 속성은 쿠키를 송출하는 범위를 특정 디렉토리에 한정할 수 있습니다. 그러나 이 지정을 피하는 방법이 있어서 보안 효과는 기대할 수 없습니다.
Domain=도메인명
- 쿠키 적용 대상이 되는 도메인명 (지정하지 않은 경우는 쿠키를 생성한 서버의 도메인)
쿠키의 domain 속성에 의해서 지정된 도메인명은 후방 일치가 됩니다. 예를 들면, “example.com”
로 지정했을 때 “example.com”
이외에 “www.example.com”
과 “www2.example.com”
등에서도 쿠키가 송출됩니다. 그렇기 때문에 명시적으로 여러 도메인에 대해서 쿠키를 송출하는 경우를 제외하고 domain 속성은 지정하지 않는 쪽이 안전합니다.
Secure
Set-Cookie: name=value; secure
- HTTPS로 통신하고 있는 경우에만 쿠키를 송신
쿠키의 secure 속성은 웹 페이지가 HTTPS에서 열렸을 때에만 쿠키 송출을 제한하기 위해서 지정하며 secure 속성을 생략한 경우에는 HTTP와 HTTPS에서도 쿠키를 반송합니다.
HttpOnly
- 쿠키를 JavaScript(자바스크립트)에서 액세스하지 못하도록 제한
쿠키의 HttpOnly 속성은 자바스크립트를 경유해서 쿠키를 취득하지 못하도록 하는 쿠키의 확장 기능입니다. 크로스 사이트 스크립팅(XSS)으로부터 쿠키의 도청을 막는 것을 목적으로 하고 있습니다.
Cookie
Cookie: status=enable
Cookie 헤더 필드는 클라이언트가 HTTP의 상태 관리 지원을 원할 때 서버로부터 수신한 쿠키를 이후의 리퀘스트에 포함해서 전달합니다. 쿠키를 여러 개 수신하고 있을 때에는 쿠키를 여러 개 보내는 것도 가능합니다.
- 서버에서 수신한 쿠키 정보
- 요청 헤더에 포함
브라우저 캐시 vs 쿠키
브라우저 캐시를 사용하면 이미지, 비디오, CSS/JavaScript 등을 포함한 특정 정적 파일을 저장할 수 있습니다. 이는 단방향 관계입니다. 해당 파일은 일단 저장되면 서버와 다시 통신하지 않습니다. 또한 브라우저 캐시는 특정 사용자를 식별하지 않고 모든 사용자를 동일하게 취급하며 사이트 속도를 개선하고 서버의 부하를 줄이는 데 도움이 됩니다.
쿠키는 각 방문자에게 고유한 정보를 추적, 식별 또는 저장할 수 있는 작은 텍스트 기반 파일입니다. 이는 서버가 쿠키에서 정보를 읽을 수 있는 양방향 관계입니다. 쿠키는 사용자가 로그인했는지 인식하거나 방문자를 식별하여 전자 상거래 상점에서 장바구니에 있는 항목을 표시하는 등 더 나은 사용자 경험을 제공하는 데 도움이 됩니다. 쿠키는 방문자가 이미 이메일 목록을 구독한 후에 이메일 수신 동의 팝업을 표시하지 않도록 쿠키를 설정하는 것과 같이 특정 방문자를 추적하고 식별하는 데 도움이 될 수 있습니다.
기본적으로 설정하는 캐싱 요청은 GET Method 뿐이고 나머지 POST, PUT 등 기타 요청 메소드들은 오리진으로 향하게 되는데 POST 요청 등 기타 요청 메소드들에 한 해서도 엣지 서버에서 처리할 수 있도록 하기 위해서 쿠키를 발행하고 해당 쿠키를 통해 엣지 서버에서도 POST 요청을 처리하게 한다.
AWS CloudFront에서의 쿠키
쿠키 기반의 콘텐츠 캐싱 (CloudFront)
CloudFront에서는 요청 및 응답을 처리할 때나 엣지 로케이션의 객체를 캐싱할 때 쿠키를 기본적으로 고려하지 않습니다. Cookie 헤더의 내용을 제외하고 동일한 두 개의 요청을 CloudFront가 수신하면 기본적으로 CloudFront는 요청을 동일하게 처리하고 두 요청에 대해 동일한 객체를 반환합니다.
최종 사용자 요청의 쿠키 일부 또는 전체를 오리진으로 전달하고, 전달되는 쿠키 값에 따라 별도의 객체 버전을 캐싱하도록 CloudFront를 구성할 수 있습니다. 이렇게 하면 CloudFront에서 최종 사용자 요청에서 전달하도록 구성된 일부 또는 전체 쿠키를 사용하여 캐시의 객체를 고유하게 식별합니다.
예를 들어, locations.html에 대한 요청에 country 또는 uk 값을 가진 fr 쿠키가 포함되어 있다고 가정합니다.
country 쿠키 값을 기반으로 객체를 캐싱하도록 CloudFront를 구성할 경우, CloudFront에서는 locations.html에 대한 요청을 오리진에 전달하고 country 쿠키 및 쿠키 값 을 포함합니다. 오리진에서는 locations.html을 반환하고 CloudFront에서는 country 쿠키의 값이 uk인 요청에 대해 한 번, 값이 fr인 요청에 대해 한 번, 객체를 캐싱합니다.
Amazon S3 및 일부 HTTP 서버에서는 쿠키를 처리하지 않습니다. 쿠키를 처리하지 않거나 쿠키에 따라 다른 응답을 제공하지 않는 오리진에 쿠키를 전달하도록 CloudFront를 구성하지 마십시오. 그렇지 않으면 CloudFront가 동일한 객체에 대해 더 많은 요청을 오리진에 전달할 수 있으므로 성능이 저하되고 오리진의 로드가 증가합니다. 앞의 예제를 예로 들면, 오리진이 country 쿠키를 처리하지 않거나 locations.html 쿠키의 값에 관계없이 항상 동일한 버전의 country을 CloudFront로 반환하는 경우 해당 쿠키를 전달하도록 CloudFront를 구성하지 마세요.
쿠키 전달을 구성하려면 배포의 캐시 동작을 업데이트합니다. 캐시 동작에 대한 자세한 내용은 캐시 동작 설정(특히 쿠키 전달 및 화이트리스트 쿠키 단원)를 참조하세요.
다음 중 하나를 수행하도록 각 캐시 동작을 구성할 수 있습니다.
- 오리진에 모든 쿠키 전달 - CloudFront가 오리진에 요청을 전달할 때 최종 사용자가 보내는 모든 쿠키를 포함시킵니다. 오리진에서 응답을 반환할 때 CloudFront는 최종 사용자 요청의 쿠키 이름 및 쿠키 값을 사용하여 응답을 캐싱합니다. 오리진 응답에 Set-Cookie 헤더가 포함되면 CloudFront는 요청된 객체와 함께 최종 사용자에게 해당 헤더를 반환합니다. 또한 CloudFront는 오리진에서 반환된 객체와 함께 Set-Cookie 헤더를 캐싱하고 모든 캐시 적중 시 최종 사용자에게 해당 Set-Cookie 헤더를 보냅니다.
- 지정한 쿠키 세트 전달 - CloudFront는 요청을 원본에 전달하기 전에 뷰어가 보내는 쿠키 중 허용 목록에 없는 모든 쿠키를 제거합니다. CloudFront는 뷰어 요청에 나열된 쿠키 이름과 값을 사용하여 응답을 캐시합니다. 오리진 응답에 Set-Cookie 헤더가 포함되면 CloudFront는 요청된 객체와 함께 최종 사용자에게 해당 헤더를 반환합니다. 또한 CloudFront는 오리진에서 반환된 객체와 함께 Set-Cookie 헤더를 캐싱하고 모든 캐시 적중 시 최종 사용자에게 해당 Set-Cookie 헤더를 보냅니다.
- 오리진에 쿠키를 전달하지 않음 - CloudFront는 최종 사용자가 보낸 쿠키에 따라 객체를 캐싱하지 않습니다. 또한 CloudFront는 오리진에 요청을 전달하기 전에 쿠키를 제거하고 최종 사용자에게 응답을 반환하기 전에 응답에서 Set-Cookie 헤더를 제거합니다.
액세스 로그
요청 및 쿠키를 로그하도록 CloudFront를 구성하면 CloudFront에서 원본에 쿠키를 전달하지 않도록 구성하거나 특 정 쿠키만 전달하도록 CloudFront를 구성한 경우에도 CloudFront는 모든 쿠키와 모든 쿠키 속성을 로그합니다.
대소문자 구분
쿠키 이름과 값은 모든 대소문자를 구분합니다. 예를 들어 CloudFront가 모든 쿠키를 전달하도록 구성되어 있고 동일한 객체에 대한 두 개의 최종 사용자 요청에 대소문자를 제외하고 동일한 쿠키가 있는 경우 CloudFront는 객체를 두 번 캐싱합니다.
CloudFront에서 쿠키 정렬
CloudFront가 쿠키(전체 또는 일부)를 전달하도록 구성된 경우 CloudFront에서는 요청을 원본에 전달하기 전에 쿠키 이름을 기준으로 쿠키를 자연스러운 순서로 정렬합니다.
If-Modified-Since 및 If-None-Match
CloudFront가 쿠키(전체 또는 일부)를 전달하도록 구성된 경우 If-Modified-Since 및 If-None-Match 조건부 요청이 지원되지 않습니다.