쿠키는 브라우저에 저장되는 작은 크기의 문자열로 HTTP 프로토콜의 일부이다. HTTP 프로토콜은 Stateless이다. 즉, 서버가 클라이언트의 상태를 보존하지 않는다.
그럼 각각의 클라이언트를 식별해야 하는 경우(로그인)는 어떻게 해결할까? 이때 쿠키를 사용하여 해결할 수 있다.
Set-Cookie
에 담긴 세션id 정보를 사용해 쿠키를 설정한다.Cookie
HTTP 헤더안에 설정된 쿠키를 포함하여 요청을 보낸다.이렇게 쿠키는 클라이언트 식별과 같은 인증에 가장 많이 쓰인다.
이외에도 쿠키는 다음과 같은 경우 사용된다.
document.cookie
를 이용하면 브라우저에서 쿠키를 접근할 수 있고, 다음과 같이 개발자 도구의 Application 탭에서 확인할 수도 있다.
document.cookie
는 name=value
쌍으로 구성되어있고, 각 쌍은 ;
로 구분한다.
document.cookie
에 직접 값을 쓸 수 있다. document.cookie
에 값을 할당하면, 브라우저는 이 값을 받아 해당 쿠키를 갱신한다.
document.cookie="test=hi";
document.cookie
를 통해 방금 생성한 쿠키를 볼 수 있다.
Application 탭에서도 다음과 같이 쿠키가 생성된 것을 볼 수 있다.
document.cookie=
연산은 모든 쿠키를 덮어쓰는 것이 아닌 며잇된 쿠키의 값만 갱신한다. 쿠키의 이름과 값엔 모든 글자가 허용되지만 형식의 유효성을 일관성 있게 유지하기 위해 encodeURIComponent
를 사용하여 이름과 값을 이스케이프 처리해준다.
document.cookie = encodueURIComponent('name') + '=' + encodueURIComponent('value');
encodeURIComponent
로 인코딩한 이후의 name=value
쌍은 4KB를 넘을 수 없다.쿠키에는 몇가지 옵션이 있는데 몇몇 옵션은 꼭 지정해 줘야 할만큼 중요하다.
옵션은 key=value
뒤에 나열하고 ;
로 구분한다.
document.cookie = "test=hi; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT";
개발자 도구의 Application 탭에서도 확인할 수 있다.
path=/mypath
이 경로나 이 경로의 하위 경로에 있는 페이지만 쿠키에 접근할 수 있다. 절대 경로이어야 하고, 기본값은 현재 경로이다.
path=/practice
에서 설정한 쿠키는 /practice
와 /practice/test
에선 볼 수 있지만, /playground
에선 볼 수 없다.
practice/index.html
practice/test.html
playground/index.html
특별한 경우가 아니라면, path
옵션을 path=/
같이 루트로 설정해 웹사이트 모든 페이지에서 쿠키에 접근할 수 있도록 하는 것이 좋다.
domain=site.com
쿠키에 접근 가능한 도메인을 지정한다. domain
옵션에 아무 값도 넣지 않았다면, 쿠키를 설정한 도메인에서만 쿠키에 접근할 수 있다. site.com
에서 설정한 쿠키는 other.com
에서 얻을 수 없다.
또한 서브 도메인이나 다른 도메인에서 쿠키에 접속할 방법은 없다. 이런 제약 사항은 안정성을 높이기 위해 만들어졌다.
하지만 서브 도메인에서 쿠키 정보를 얻는 방법이 완전히 없는 것은 아니다. 쿠키를 설정할 때 domain
옵션에 루트 도메인을 명시적으로 설정해 주면 된다.
document.cookie = "test=hi; domain=test.com";
//sub.test.com와 같은 서브도메인에서도 쿠키 정보를 얻을 수 있다.
console.log(document.cookie) // test=hi 를 확인 가능
구식 브라우저를 지원하려면 domain=.site.com
같이 .
을 앞에 붙인 표기법을 사용하는 것이 좋다.
서브 도메인이란 도메인 이름의 확장자 역할을 하여 웹사이트의 다양한 섹션을 구성 및 탐색할 수 있도록 지원한다. 또한 서브 도메인은 입력하고 기억하기 쉬운 것이어야 한다.
store.yoursite.com에서 store가 하위 도메인이고 yoursite가 주 도메인이며 .com은 최상위 도메인이다.
출처: https://kr.godaddy.com/help/what-is-a-subdomain-296
expires나 max-age 옵션이 지정되어있지 않으면, 브라우저가 닫힐 때 쿠키도 함께 삭제된다. 이런 쿠키를 세션 쿠키라고 부른다.
expires
나 max-age
옵션을 설정하면 브라우저를 닫아도 쿠키가 삭제되지 않는다.
expires=Sat, 23 Oct 2021 15:00:00 GMT
브라우저는 설정된 유효 일자까지 쿠키를 유지하며, 해당 알지가 도달하면 쿠키를 자동 삭제한다.
쿠키의 유효 일자는 반드시 GMT 포맷으로 설정한다. date.toUTCString
을 통해 해당 포맷으로 쉽게 변경 가능하다.
document.cookie = `test=hi; expires=${date.toUTCString()}`;
max-age=3600
max-age
는 expires
옵션의 대안으로, 쿠키 만료 기간을 설정할 수 있게 해준다. 현재부터 설정하고자 하는 만료일시까지의 시간을 초로 환산한 값을 설정한다.
// 1분 후 쿠키 삭제
document.cookie = "test=hi; max-age=60";
secure
이 옵션을 설정하면 HTTPS로 통신하는 경우에만 쿠키가 전송된다.
document.cookie = "test=hi; secure";
samesite
옵션은 크로스 사이트 요청 위조(cross-site request forgery, XSRF) 공격을 막기 위해 만들어진 옵션이다.
samesite
의 옵션엔 두 가지 값(strict, lax)을 설정할 수 있다.
samesite=strict
(default 값)사용자가 사이트 외부에서 요청을 보낼 때, samesite=strict
옵션이 있는 쿠키는 절대로 전송되지 않는다. 예를 들어 메일에 있는 링크를 따라 접속하거나 다른 사이트에서 폼을 전송하는 경우 등과 같이 제 3자의 도메인에서 요청이 이뤄질 땐 쿠키가 전송되지 않는다.
samesite=lax
lax
는 strict
보다 느슨하면서도 XSRF 공격을 막을 수 있는 접근법이다. lax
도 사이트 외부에서 요청을 보낼 때 브라우저가 쿠키를 보내는 것을 막지만 예외가 있다.
다음 두 조건을 동시에 만족하면 쿠키가 전송된다.
<iframe>
안에서 탐색이 일어나거나 AJAX 요청은 이 조건에 해당하지 못한다.samesite
는 오래된 브라우저에선 지원하지 않는다는 문제점이 있다.
httpOnly
옵션은 웹서버에서 Set-Cookie
헤더를 이용해 쿠키를 설정할 때 지정할 수 있다.
이 옵션은 자바스크립트 같은 클라이언트 측 스크립트가 쿠키를 사용할 수 없게 한다. document.cookie
를 통해 쿠키를 볼 수도 없고 조작할 수 도 없다.
httpOnly
를 통해서 악의적으로 코드를 이용하여 쿠키에 접근하는 것을 방지할 수 있다.