
쿠키, localStorage.. 매번 옵션에 대해 기억이 나질 않아 정리를 해본다🍪
Web Storage
웹 스토리지 객체인 localStorage와 session Storage는 브라우저 내에 키-값 쌍을 저장할 수 있게 해준다.
Local Storage
LocalStorage를 잘 사용하기 위해서는 저장된 데이터의 위협 수준이 매우 낮아야 한다. 추가적으로 쉽게 해킹되지 않도록 저장된 데이터를 암호화하는 것이 좋다.
- HTML5가 나온 이후 쿠키의 많은 사용 방법들은 LocalStorage 방법으로 대체되었다.
- origin이 같은 경우 데이터는 모든 탭과 창에서 공유된다. (origin(domain, port, protocol))만 같으면 url 경로가 달라도 동일한 결과를 볼 수 있다.)
- 브라우저가 OS가 재시작하더라도 데이터가 파기되지 않는다.
Session Storage
- localStorage보다 자주 사용되지는 않는다. 제공하는 프로퍼티는 같지만, 훨씬 제한적이기 때문.
- 현재 떠 있는 탭에서만 유지된다. 같은 페이지라도 다른 탭이라면 다른 곳에 저장되기 때문이다.
- 페이지를 새로 고침해도 데이터가 유지된다. 하지만 탭을 닫고 새로 열 때는 사라진다.
쿠키 외의 방식을 사용하는 이유
쿠키를 사용하면 브라우저 데이터를 저장할 수 있는데, 왜 또 다른 객체를 사용해 데이터를 저장하는 걸까? 이유로는 아래와 같다.
- 쿠키와 다르게 웹 스토리지 객체는 네트워크 요청 시 서버로 전송되지 않는다. HTTP 요청에서 데이터를 주고받지 않기 때문에 클라이언트와 서버간의 전체 트래픽과 낭비되는 대역폭의 양을 줄일 수 있다.
- LocalStorage는 최대 5MB의 데이터를 저장할 수 있다. 쿠키가 저장할 수 있는 최대 4KB 용량보다 훨씬 많은 용량이다.
- 쿠키와 또 다른 점은 서버가 HTTP 헤더를 통해 스토리지 객체를 조작할 수 없다는 점. 웹 스토리지 객체 조작은 모두 JavaScript 내에서 수행된다.
- 웹 스토리지 객체는 도메인, 프로토콜, 포트로 정의되는 origin에 묶여있다. 따라서 프로토콜과 서브 도메인이 다르면 데이터에 접근할 수 없다.
작지만 강력한 Cookies
- 쿠키는 브라우저에 저장되는 작은 크기의 문자열로, RFC 6265 명세에서 정의한 HTTP 프로토콜의 일부이다.
- 쿠키는 주로 웹 서버에 의해 만들어진다. 서버가 HTTP 응답 헤더의 Set-Cookie에 내용을 넣어 전달하면, 브라우저는 이 내용을 자체적으로 브라우저에 저장한다. 브라우저는 사용자가 쿠키를 생성하도록 한 동일 서버(사이트)에 접속할 때마다 쿠키의 내용을 Cookie 요청 헤더에 넣어서 함께 전달한다.
- 쿠키는 클라이언트 식별과 같은 인증에 가장 많이 쓰인다.
- 쿠키는 최대 4KB의 용량을 가진 매우 작은 양의 데이터이다. 그리고 도메인 하나당 저장할 수 있는 쿠키의 개수는 20여 개 정도로 한정되어 있다. (브라우저에 따라 조금씩 다르다.)
- 문자열만 저장할 수 있다.
- 쿠키의 또 다른 용도로는 사이트에서 제한된 인터넷 사용 기록을 기반으로 사용자 경험을 개선하는 것이다.
Persistent Cookies
Persistent Cookies는 만료일을 가진다. 이 쿠키는 만료일까지 유저의 디스크에 저장되고 만료일이 지나면 삭제된다. 유저들이 방문할 때마다 유저 경험을 커스텀하기 위해 특정 웹사이트에서 행동을 기록하는 등 여러 활동들에 사용될 수 있다.
Session Cookies
세션 쿠키는 만료일을 포함하지 않는다. 대신에 브라우저나 탭이 열려있는 동안에만 저장된다. 이 유형의 쿠키는 탭을 닫으면 모든 정보를 잊어버리기 때문에 은행 유저들의 자격 증명을 저장하는 데 사용될 수 있다.
쿠키에 접근하기
document.cookie
프로퍼티를 이용하면 브라우저에서도 쿠키에 접근할 수 있다.
쿠키 쓰기
document.cookie
에 직접 값을 쓸 수 있다. 이때 cookie는 데이터 프로퍼티가 아닌 접근자 프로퍼티이다. 접근자 프로퍼티에 값을 할당하는 것은 데이터 프로퍼티에 값을 할당하는 것과는 조금 다르게 처리된다.
document.cookie
에 값을 할당하면, 브라우저는 이 값을 받아 해당 쿠키를 갱신한다. 이때, 다른 쿠키의 값은 변경되지 않는다.
document.cookie = 'user=John' // 이름이 user인 쿠키의 값만 갱신한다.
쿠키의 이름과 값에는 특별한 제약이 없기 때문에 모든 글자가 허용된다. 하지만 형식의 유효성을 일관성 있게 유지하기 위해 반드시 내장 함수 encodeURIComponent
를 사용하여 이름과 값을 이스케이프 처리해 줘야 한다.
const name = 'my name'
const value = 'John Smith' // 특수 값인 공백은 인코딩 처리해 줘야 한다.
document.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value)
alert(document.cookie) // ...; my%20name=John%20Smith
쿠키를 쓸 때 옵션은 key, value 쌍 뒤에 ;
로 구분해줘야 한다.
document.cookie = "user=John"; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT"
쿠키 설정
domain
domain=site.com
- 쿠키에 접근 가능한 도메인을 설정한다. domain 옵션에 아무 값도 넣지 않았다면 쿠키를 설정한 도메인에서만 쿠키에 접근할 수 있다. 이 외의 까다로운 제약사항으로는 서브 도메인에서도 쿠키 정보를 얻을 수 없다는 점이다.
- 서브 도메인이나 다른 도메인에서 쿠키에 접속할 방법은 없다.
site.com
에서 생성한 쿠키를other.com
에선 절대 전송받을 수 없다. 이런 제약사항은 안정성을 높이기 위해 만들어졌다. 민감한 데이터가 저장된 쿠키는 관련 페이지에서만 볼 수 있도록 하기 위해서 말이다. 하지만 domain 옵션에 루트 도메인을 명시적으로 설정하면 서브 도메인에서도 쿠키에 접근할 수 있다.
document.cookie = 'user=John; domain=site.com'
이렇게 설정하면 forum.site.com 같은 서브도메인에서도 쿠키 정보를 얻을 수 있다.
expires와 max-age
expires나 max-age(만료 기간) 옵션이 지정되어 있지 않으면, 브라우저가 닫힐 때 쿠키도 함께 삭제된다. 이런 쿠키를 Session Cookie 라고 부른다.
- 브라우저는 설정된 유효 일자까지 쿠키를 유지하다가, 해당 일자가 도달하면 쿠키를 자동으로 삭제한다.
- 쿠키의 유효 일자는 반드시 GMT(Greenwich Mean Time) 포맷으로 설정해야 한다.
date.toUTCString
을 사용하면 해당 포맷으로 쉽게 변경할 수 있다.
const date = new Date(Date.now() + 86400e3)
date = date.toUTCString()
document.cookie = 'user=John; expires=' + date
- max-age는 expires 옵션의 대안으로, 쿠키 만료 기간을 설정할 수 있게 해준다. 현재부터 설정하고자 하는 만료일시까지의 시간을 초로 환산한 값을 설정한다.
- 0이나 음수값을 설정하면 쿠키는 바로 삭제된다.
document.cookie = 'user=John; max-age=3600'
secure
이 옵션을 설정하면 HTTPS로 통신하는 경우에만 쿠키가 전송된다.
secure
옵션이 없으면 기본 설정이 적용되어 프로토콜 상관없이 읽을 수 있게 된다. 쿠키는 기본적으로 도메인만 확인하지 프로토콜을 따지진 않기 때문이다.
samesite
쿠키의 samesite
옵션을 이용하면 “XSRF 보호 토큰” 없이도 크로스 사이트 요청 위조(cross-site request forgery, XSRF) 공격을 막을 수 있다. 속성으로는 none
, strict
, lax
가 있다.
XSRF 공격: 크로스 사이트 요청 위조(cross-site request forgery, XSRF) 공격
XSRF는 웹 애플리케이션 보안 취약점 중 하나이다. 사용자가 자신의 의지와 동의 없이 악의적인 요청을 다른 웹사이트에 보내는 공격을 말한다.
공격 예시:
- 사용자가 악의적인 웹사이트를 방문하여 그 웹사이트의 스크립트가 인증된 사용자를 대상으로 다른 사이트에 요청을 보내도록 한다.
- 사용자는 그 악의적인 웹사이트를 방문했던 것을 모르고, 자신의 웹메일, 소셜 미디어 등을 사용한다.
- 악의적인 웹사이트가 사용자의 세션 쿠키를 이용하여 인증된 사용자처럼 보이도록 요청을 보내고, 그 결과로 사용자의 계정에 해를 끼친다.
공격을 막기 위해 모든 요청을 검수하거나 모든 폼에 보호 토큰을 세팅할 수 있다. 이런 절차는 구현에 시간이 걸린다는 단점이 있다.
samesite 옵션 - strict
사용자가 사이트 외부에서 요청을 보낼 때 samesite=strict
옵션이 있는 쿠키는 절대로 전송되지 않는다.
samesite 옵션 - lax
사용자 경험을 해치지 않으면서 XSRF 공격을 막을 수 있는 느슨한 접근법이다. strict와 마찬가지로 lax도 사이트 외부에서 요청을 보낼 때 브라우저가 쿠키를 보내는 걸 막아주지만 예외사항이 존재한다.
아래 두 조건을 동시에 만족할 때는 samesite=lax 옵션을 설정한 쿠키가 전송된다.
- “안전한” HTTP 메서드인 경우(예: GET 방식. POST 방식은 해당하지 않음).
- 작업이 최상위 레벨 탐색에서 이루어질 때(브라우저 주소창에서 URL을 변경하는 경우).
브라우저 크롬의 경우 lax
가 기본값이다.
httpOnly
이 옵션은 자바스크립트 같은 클라이언트 측 스크립트가 쿠키를 사용할 수 없게 한다. document.cookie
를 통해 쿠키를 볼 수도 없고 조작할 수도 없다. httpOnly
옵션이 설정된 쿠키는 document.cookie
로 쿠키 정보를 읽을 수 없기 때문에 쿠키를 보호할 수 있다.
서드 파티 쿠키
사용자가 방문 중인 도메인이 아닌 다른 도메인에서 설정한 쿠키를 "서드 파티 쿠키(third-party cookie)"라고 부른다. 광고회사는 사용자의 이용 행태를 추적하고, 광고를 제공하기 위해 오래전부터 서드 파티 쿠키를 사용하고 있다.