본문 바로가기

JavaScript

쿠키, 세션, 로컬스토리지

쿠키

설명

  • 로그인상황을 예시로, 로그인이 성공하면 서버는 클라이언트에 일종의 인증서를 보내준다.
  • 클라이언트가 이것을 가지고오면 어떤사람인지 구분하는데 사용하기로한다.
  • 클라이언트는 request를 보낼 때 마다 이 인증서를 request에 포함해서 보내야한다.
  • 이 때 사용하는 것이 쿠키이다.
  • 로그인에 성공했을 때 서버가 Set-Cookie헤더로 쿠키의 값을 보내준다.
  • 클라이언트는 저장해두었다가, 서버에 Request를 보낼 때 마다 매번 Cookie헤더로 보내주어 로그인상태라는 것을 표시한다.
  • 웹브라우저를 껐다 키거나, 컴퓨터를 껐다 키더라도 쿠키값은 유지되기 때문에 일정기간 로그인하지않아도 로그인상태가 유지된다.

특징

  • 서버로부터 response로 쿠키를 받으면, 클라이언트에서는 별도로 작업을 해주지 않아도 웹브라우저가 알아서 저장하고, request를 보낼 때에도 알아서 보낸다.
  • 자바스크립트를 통해서 쿠키값을 추가, 수정, 참조할 수 있다. (따라서 보안에 취약하다.)
  • 민감하거나 중요한 정보를 담으면 안된다.
  • 수명을 지정할 수 있고, 수명이 다한 쿠키는 알아서 지워진다.

사용방법

서버에서 response할 때

  • 서버에서 Set-Cookie헤더를 response로 보내주면, 웹브라우저는 알아서 쿠키값을 저장해둔다.
Set-Cookie: session-id=1234; Domain=codeit.kr; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=2592000;
  • session-id: key
  • 1234: value
  • Domain, Path, SameSite: attribute
  • 모든 attribute이름들은 대소문자를 구분하지 앟는다.(set-cookie, domain, path, samesite 로 작성해도 같은 동작을 한다.)

클라이언트에서 request할 때

  • request를 보낼 때 주소에 해당하는 쿠키가 저장되어있다면 웹브라우저가 알아서 쿠키를 보내준다.

자바스크립트로 사용하기

  • 보통은 서버가 쿠키값을 만들고, 클라이언트에서는 웹 브라우저에 맡기고 건드리지 않는 것이 권장된다.
  • 하지만 클라이언트에서 자바스크립트로 쿠키를 생성/수정/참조 하는 것이 가능하다.

추가, 수정하기

  • 변수할당처럼 보이지만, 이 코드는 새로운 쿠키를 추가하거나(기존에 session-id라는 쿠키가 있다면) 수정하는 코드이다.
document.cookie = "session-id=1234; Domain=codeit.kr; Path=/; HttpOnly; Secure; SameSite=Strict; Max-Age=2592000;";

값 참조하기

  • document.cookie 값을 참조하면 모든 쿠키의 키와 값이 ';' 문자로 구분된 문자열을 확인할 수 있다.
  • split() 함수를 사용해서 직접 분리하거나, cookie라는 npm패키지를 활용하는 등 다양한 방법으로 사용할 수 있다.

값 지우기

  • Max-Age속성의 값을 0으로 업데이트하면 수명이 0이 되므로 지워진다.
document.cookie = "session-id; Max-Age: 0;";

사용되는 예시

  • 로그인창의 아이디 자동완성
  • 공지 팝업 하루 안보기
  • 쇼핑몰에서 로그인 안한상태로 장바구니 담기
  • 등 사용자의 편의를 위하되, 지워지거나 조작되거나 가로채여도 큰일이 없을 수준의 정보를 브라우저에 저장한다.

Attribute

domain

path

  • 브라우저가 쿠키를 보낼 경로를 지정한다.
  • 예를들어 'path=/' 라고 설정했다면, '/' 아래에 있는 경로들, '/abc', '/abc/def' 같은 경로에 request를 보낼 때에도 모두 쿠키를 보낸다.

httpOnly

  • document.cookie값을 자바스크립트로 사용할 수 있으며 해커들이 악성코드를 사용자들에게 유포해 쿠키를 훔칠 수도 있다.
  • 로그인정보같은 민감한 정보는 되도록이면 자바스크립트로 조작하지 말아야한다.
  • HttpOnly를 사용하면 쿠키를 자바스크립트로 사용하지 못하게 막을 수 있다.

secure

  • secure를 지정하면, 'Https' 로 리퀘스트를 보낼 때에만 쿠키를 보낸다.(http 로 보낼때에는 보내지않는다.)
  • secure설정을 했을지라도 쿠키는 본질적으로 안전하지 않기때문에 민감한 정보는 저장하면 안된다.
  • 참고로 sameSite를 지정하면, Secure도 함께 지정해야한다.

sameSite

  • 자바스크립트를 사용하면 현재 사이트에서 다른 사이트로 리퀘스트를 보낼 수 있고, 사이트의 링크를 클릭하면 웹 브라우저는 다른 사이트로 GET리퀘스트를 보내며 이동한다.
  • 그리고 이미지 파일을 다운받거나 할 때에도 GET리퀘스트를 보내서 받는다.
  • 예를들어 codeit.kr 이라는 사이트에서 쿠키를 발급해서 사용자가 저장하고 있는데, 사용자가 hacker-site.com 이라는 악성 사이트에 접속하는 상황이 온다면, 이 악성사이트는 codeit.kr이라는 사이트로 리퀘스트를 보내서 개인정보를 탈취할 수 있다. 이러한 공격을 크로스 사이트 요청 위조(CSRF, XSRF)라고 부른다.
  • 이것을 방지하기 위해서 제 3자 사이트에서 쿠키를 보내지 못하게 SameSite 속성을 설정하는 것이다.
  • sameSite속성의 값에는 Strict, Lax, None 이 있다.
  SameSite=Strict SameSite=Lax SameSite=None
다른 사이트에서 우리 사이트로 리퀘스트를 보낼 X X O
다른 사이트에서 이미지 파일 등을 받을 X X O
다른 사이트에서 사용자가 링크를 클릭해 우리 사이트로 이동할 X O O
우리 사이트에서 우리 사이트로 리퀘스트를 보낼 O O O

expires

Set-Cookie: id=a3fWa; Expires=Tue, 31 Oct 2023 07:28:00 GMT;
  • 쿠키가 만료될 시기를 설정할 수 있다.

max-age

  • 쿠키의 수명을 지정하는 속성이다.

세션쿠키와 영속적 쿠키

세션 쿠키(Session Cookie)는 Expires나 Max-age를 지정하지 않으면 만들 수 있다. 세션 쿠키는 브라우저를 닫으면 지워지는 쿠키이다.

영속적 쿠키(Persistent Cookie)는 Expires나 Max-age로 수명을 지정해서 만들 수 있다. 수명이 다하면 지워진다.


쿠키 사용시 주의점

예전에 구글, 페이스북 등 빅테크들이 쿠키를 사용해서 사용자의 정보를 과도하게 수집하고 자사 광고에 활용해 논란이 된 적이 있다.

그래서 유럽연합에서는 개인정보의 범위를 넓혀 직간접적으로 개개인을 식별할 수 있는 데이터 까지 개인정보라는 규정을 만들게 되었다.

여기에 쿠키데이터도 포함된다.

 

따라서 쿠키를 사용하는 경우, GDPR(일반 정보 보호 규정 General Data Protection Regulation)규정에 따르면 개인정보 이용 목적을 안내하고, 사용자 동의를 받는 절차가 꼭 필요하다.

그래서 최근 많은 사이트들이 처음 들어가면 팝업을 띄우고 동의를 받는다.

쿠키릐 사용은 앞으로도 점점 까다로워질 것이니 지금부터 서드파티 쿠키를 사용하지 못한다는 전제하에 서비스를 개발하는 것도 좋겠다.

 

서드파티 : 사용자가 접속해있는 페이지와 다른 도메인으로 전송되는 쿠키


react에서 cookie사용하기

npm install react-cookie
//cookie.js
import { Cookies } from "react-cookie"

const cookies = new Cookies();
export const setCookie = (name, value, option) => {
	return cookies.set(name, value, {...option});
}

export const getCookies = (name) => {
	return cookies.get(name);
}
  • 이렇게 쿠키를 다루는 함수를 만들어두고 필요한 곳에서 가져다쓴다.

세션

  • 민감하거나 중요한 정보를 서버쪽에 저장해두기 위한 것.
  • 서버는 기한이 짧은 임시키를 브라우저에 쿠키로 준다.
  • 누군가에게 노출되면 안되기때문에 서비스 제공자가 직접 관리해야하는 데이터들은 세션으로 서버안에서 다뤄진다.
  • 사이트를 만들 때, 세션에 저장할지 쿠키로 저장할지 고려해보자.
  • 세션에만 너무 많은 데이터를 넣으면 서버에 부하가 생길수도 있다.

캐시

  • 웹 뿐 아니라 컴퓨터의 메모리부분이나 안드로이드 등 다양한 곳에 쓰인다.
  • 공통적인 의미로, 가져오는데 비용이 드는 데이터를 한 번 가져온 뒤에는 임시로 저장해두는 것을 의미한다.
  • 이미지같은 정보를 가져올 때, 데이터 사용량도 발생하고 시간도 들기때문에 사용자가 여러번방문할 법한 사이트에서는 한 번 받아온 데이터를 사용자의 컴퓨터 또는 중간역할을 하는 서버에 저장해둔다.

세션 스토리지와 로컬 스토리지

  • 쿠키는 서버에서 만들고 클라이언트는 거의 건드리지 않는다.
  • 하지만 사이트에 따라서 클라이언트에서만 사용하는 데이터를 저장해놓고 사용하고 싶은 경우가 생긴다.
  • 이런 목적으로 나온 것이 세션스토리지, 로컬 스토리지이다.
  • 해당 데이터들은 서버에 전송되지않는다.

세션스토리지

  • 현재 탭에서만 유효한 저장소로 탭을 닫으면 데이터가 사라진다.
  • 다른 탭과 데이터가 공유되지 않는다.
  • IndexedDB 키와 같은, 소량의 세션 관련 정보를 저장하는 데 유용할 수 있다.
  • 동기식으로 동작하며, 기본 스레드를 차단하므로 주의해야한다. >> 이게 무슨말일까?

 

아래는 현재 탭의 인풋값을 저장하고 참조하는 코드이다. 저장하는 데이터 타입은 문자열이다.

// 값을 저장하는 코드. (이미 값이 있다면) 수정하는 코드
const data = inputElement.value;
sessionStorage.setItem('draft', data);

// 값을 참조해서 사용할 때
const draftData = sessionStorage.getItem('draft');

// 값 지우기
sessionStorage.removeItem('draft');

로컬스토리지

  • 해당 사이트에서 유요한 저장소로, 탬을 닫거나 브라우저를 닫아도 데이터가 유지된다.
  • 여러 탭 사이에서도 데이터가 공유된다.
  • 동기식이며, 기본스레드를 차단하므로 피해야한다.

 

예를들, 아래는 사이트의 사이드바 보이기/감추기 정보를 저장하고 참조하는 코드이다.

문자열 형태로 저장되기때문에 원하는 데이터타입으로 바꿔줘야한다.

// 사용자가 사이드바 감추기 버튼을 클릭했을 때
// 값을 저장, 수정
localStorage.setItem('show-sidebar', 'false');

// 사용자가 처음 접속했을 때
const showSidebar = localStorage.getItem('show-sidebar') === 'true';

// 값 지우기
localStorage.removeItem('show-sidebar');

쿠키와 비교한 세션스토리지, 로컬스토리지

  • 세션/로컬 스토리지는 클라이언트가 만들고 관리하는 데이터이다.(쿠키는 서버에서만들고 클라이언트가 들고다님)
  • 자바스크립트로 편리하게 조작할 수 있다.(쿠키보다 편리하게)
  • 만료기간(수명)이 없다.
  • 쿠키보다 사용할 수 있는 용량이 크다.(브라우저에 따라 다르지만 거의 5MB)

스토리지가 변경되었을 때 발생하는 이벤트도 있다.

window.addEventListener("storage", () => {
  const showSidebar = localStorage.getItem('show-sidebar') === 'true';
    // showSidebar 값 적용하기
});

 


세션스토리지와 로컬스토리지의 공통점

  • setItem(key, value)으로 데이터를 저장
  • getItem(key)으로 해당 키의 데이터를 받아옴
  • removeItem(key)으로 키와 값을 삭제함
  • clear()로 모든 데이터를 삭제함
  • key(index)로 인덱스에 해당하는 키를 받아옴
  • length로 저장된 항목의 개수를 가져옴
  • Object.keys로 전체 키를 얻을 수 있음
  • 객체처럼 키에 접근할 수 있음(이 경우 storage이벤트는 발생하지 않는다.)
  • 전체적으로 map 객체와 비슷한 부분이 많음.

사용되는 예시

  • 초안 임시저장하기(기본적으로 초안은 로컬스토리지에 저장한다고함. 주기적으로 서버에도 저장한다. 그래서 모바일에서도 초안을 확인할 수 있다.)
  • 채팅창에 입력을 하다가 창을 닫더라도 내용이 저장된다.
  • 웹기반으로 만들어진 프로그램(웹앱)들은 세션스토리지, 로컬스토리지를 적극적으로 사용한다고 한다.
  • 노션은 LRUCache를 로컬스토리지에 저장하는것으로 보이는데, 쉽게말해 자주 쓰는 데이터를 로컬스토리지에 캐싱해두는 용도로 사용중인 것으로 보인다.

 

LRUCache : 캐시에 저장된 데이터의 접근율을 높게 유지하기위한 메모리 교체 알고리즘 중의 하나로, 가장 오랫동안 사용되지 않은 페이지를 교체의 대상으로 삼는 기법이다.

'JavaScript' 카테고리의 다른 글

웹페이지 렌더링 방식(CSR, SSR, SSG)  (0) 2023.10.29
JavaScript - ajax  (1) 2023.10.15
JavaScript - 비동기실행 순서 예제  (1) 2023.10.15
JavaScript - async/await  (1) 2023.10.13
JavaScript - 비동기 실행과 promise객체  (0) 2023.10.13