Storage for the web

최문경·2022년 4월 6일
0

개요

웹에서 리소스를 저장할 수 있는 저장소는 여러 가지가 존재합니다.

  1. Web Storage API (localStorage, sessionStorage)
  2. Cookie
  3. IndexedDB
  4. CacheStorage
  5. File System API
  6. Web SQL

우리는 이 모든 저장소를 사용해도 되는걸까요? 아니면 데이터의 종류에 따라 다른 저장소를 사용해야 하는 걸까요?


어떤 저장소를 사용해야 할까요?

아래는 유튜브 영상(Storage for the web)의 스크린샷입니다.


LocalStorage의 사용을 피하라고 하는 것일까요?

아래는 위의 영상에 나오는 분께서 작성하신 글과 localStorage 사용을 중지하라는 블로그 글을 보고 정리한 내용입니다.

  1. 동기식으로 동작하기 때문에 기본 스레드(메인 스레드)를 차단할 수 있다. (런타임이 느려질 수 있다.)
  2. 저장 용량이 제한적이다. (주요 브라우저에서 최대 5MB)
  3. 문자열만 저장할 수 있다. (더 복잡한 데이터를 저장하기 힘들다.)
  4. Web Workers, Service Workers가 접근할 수 없다.
  5. javascript로 접근할 수 있다. (보안상 좋지 않다.)

그럼 어떤 저장소를 사용해야할까요?
제가 검색한 내용을 토대로 정리해보면 공통적으로 Cache API, IndexedDB를 사용하라고 합니다.

그럼 각 저장소에는 어떤 데이터를 저장하는 것이 좋을까요?

Cache API

  • 오프라인으로 저장하는 경우 (앱을 오프라인으로 실행해야 하는 경우)
  • 앱 및 파일 기반 컨텐츠를 로드하는데 필요한 데이터

Indexed DB

  • 앱의 상태 및 사용자 생성 컨텐츠를 저장하는 경우
  • 문자열이 아닌 데이터를 브라우저에 저장해야 하는 경우

하지만, 무조건 Local Storage를 사용하지 말고 Cache APIIndexed DB를 사용해야 한다는 것은 아닙니다. 간단한 웹사이트를 만든다면 LocalStorage 사용해도 크게 문제가 되지 않을 것이기 때문입니다.

그리고 Cookie 는 HTTP 요청시 함께 보내지기 때문에 인증과 인가에 많이 사용됩니다.


각 저장소의 특징

  • LocalStorage: 동기식, 문자열만 저장, 모든 탭에서 공유, 브라우저 재시작해도 남아있음
  • SessionStorage: 동기식, 문자열만 저장, 같은 탭에서만 공유, 브라우저 닫히면 삭제
  • Cookie: 동기식, 문자열만 저장, 모든 HTTP 요청과 함께 전송 (주로 인증에 사용됨)
  • IndexedDB: 비동기식, NoSQL, 객체 지향적, window 객체와 web workers, service workers로 부터 접근 가능
  • Cache: 비동기식, window 객체와 web workers, service workers로 부터 접근 가능
  • File System API: Chromium 기반 브라우저에서만 사용할 수 있으므로 권장하지 않음.
  • Web SQL: 지원 중단 (기존 코드들 IndexedDB로 마이그레이션 해야함)

저장 용량

브라우저에 따라 다를 수 있지만 일반적으로 장치에서 사용 가능한 저장 공간의 양에 따라 결정된다고 합니다.

  • Chrome은 브라우저가 전체 디스크 공간의 최대 80%까지 사용할 수 있도록 합니다. 오리진은 전체 디스크 공간의 최대 60%를 사용할 수 있습니다. (다른 Chromium 기반 브라우저에서는 더 많은 스토리지 사용을 허용할 수도 있습니다.)
  • Firefox는 브라우저가 디스크 여유 공간의 최대 50%를 사용하도록 허용합니다.
  • Safari는 약 1GB를 허용하는 데 제한에 도달하면 사용자에게 메시지를 표시하여 제한을 200MB 단위로 늘립니다.




예를 들어, 현재 디스크 공간이 994GB라면, 994GB * 0.6 = 596.4GB를 사용할 수 있다는 것을 의미합니다.

실제로 콘솔에서 quota(byte단위) 값을 출력해보면 596797550592 Byte가 출력되는 것을 알 수 있고 GB로 변환해보면 약 596GB라는 것을 알 수 있습니다.


저장 용량 초과를 처리하는 방법

사용 가능한 할당량을 초과하면 IndexedDBCache API 모두 QuotaExceededError라는 DOMError를 발생시킵니다.

// IndexedDB
const transaction = idb.transaction(['entries'], 'readwrite');
transaction.onabort = function(event) {
  const error = event.target.error; // DOMException
  if (error.name == 'QuotaExceededError') {
    // Fallback code goes here
  }
};
// Cache API
try {
  const cache = await caches.open('my-cache');
  await cache.add(new Request('/sample1.jpg'));
} catch (err) {
  if (error.name === 'QuotaExceededError') {
    // Fallback code goes here
  }
}

에러가 포착되면 처리하는 것이 중요합니다. 예를 들어 오랫동안 액세스하지 않은 콘텐츠를 삭제하거나, 크기를 기준으로 데이터를 제거하거나, 사용자가 삭제할 항목을 선택할 수 있는 방법을 제공할 수 있습니다.

그런데, 브라우저는 quota가 초과하면 자동으로 삭제하는 로직을 가지고 있습니다.

chrome, firefox와 같은 chromium 기반의 브라우저들은 할당량이 초과하면 최근에 가장 적게 사용한 데이터를 자동으로 삭제합니다. (persistent storage - 사용자만 삭제할 수 있는 데이터 제외)

예를 들어, 현재 아래와 같이 용량이 차있다고 해봅시다.


그리고 사용자가 n 사이트에 접속하여 오프라인에서도 음악을 듣기 위해 음악을 저장했더니 저장용량이 초과했습니다.


이 때 브라우저는 persistent storage(b)를 제외하고 최근에 가장 적게 사용한 storage를 삭제합니다.

반면에 safari는 할당량이 초과하면 새로운 데이터를 막습니다. 그리고 7일 동안 데이터를 사용하고 사이트를 이용하지 않으면 사이트의 모든 데이터가 사라집니다.


사용법

1. Local Storage와 Session Storage

두 스토리지 객체는 동일한 메서드와 프로퍼티를 가집니다.

  • setItem(key, value) : 키와 값을 저장합니다.
  • getItem(key) : 키에 해당하는 값을 가져옵니다.
  • removeItem(key) : 키와 해당 값을 삭제합니다.
  • clear() : 저장된 모든 데이터를 삭세합니다.
  • key(index) : 인덱스에 해당하는 키를 가져옵니다.
  • length : 저장된 항목의 개수를 가져옵니다.

session이란?
영어에서 세션이란 어떤 활동이 수행되는 시간 블록을 가리킵니다. 따라서 웹 세션은 사용자가 첫 페이지에 도착하는 순간부터 사이트를 떠날 때까지 웹 사이트를 탐색하는데 걸리는 시간이라고 할 수 있습니다.
(In English, the word "session" refers to a discrete block of time during which an activity is performed. A web session is therefore the amount of time that a user spends browsing a given website: from the moment they arrive on the first page, to the moment they leave the site.)


2-1 쿠키에 접근하기

쿠키는 어떻게 저장될까요? 서버가 HTTP 응답 헤더의 Set-Cookie에 내용을 넣어 전달하면, 브라우저는 이 내용을 브라우저에 저장합니다.

document.cookie 프로퍼티를 이용하면 브라우저에서도 쿠키에 접근하거나 직접 값을 저장할 수 있습니다.

document.cookiename=value 쌍으로 구성되어 있고, 각 쌍은 ;으로 구분합니다. 이 때, 쌍 하나는 하나의 독립된 쿠키를 의미합니다.

따라서, ;을 기준으로 document.cookie를 분리하면 원하는 쿠키를 찾을 수 있습니다.

2-2 쿠키에 데이터 저장하기

document.cookie에 값을 할당하면 브라우저는 해당 쿠키를 업데이트하는데 다른 쿠키의 값은 변경되지 않습니다.

2-3 옵션

옵션은 key=value 뒤에 나열하고 ;로 구분합니다.

document.cookie = "user=Choi; path=/; expires=Tue, 19 Jan 2038 03:14:07 GMT"
  1. path

이 경로나 이 경로의 하위 경로에 있는 페이지만 쿠키에 접근할 수 있습니다.

// 모든 페이지에서 접근 가능하도록 하기
document.cookie = "user=Choi; path=/;

  1. domain

쿠키에 접근 가능한 domain을 지정합니다. 아무 값도 넣지 않으면 쿠키를 설정한 도메인에서만 쿠키에 접근 가능합니다.


  1. expires와 max-age

expires나 max-age 옵션이 지정되어있지 않으면, 브라우저가 닫힐 때 쿠키도 함께 사라집니다.
따라서, expiresmax-age 옵션을 설정하면 브라우저를 닫아도 쿠키가 삭제되지 않습니다.

expires 는 반드시 GMT(Greenwich Mean Time) 포맷으로 설정해야 합니다. date.toUTCString을 사용하면 해당 포맷으로 쉽게 변경할 수 있습니다.

// 유효기간이 하루인 쿠키
let date = new Date(Date.now() + 86400000);
date = date.toUTCString(); // 'Fri, 08 Apr 2022 02:11:53 GMT'
document.cookie = "user=Choi; expires=" + date;

max-ageexpires의 대안으로 좀 더 쉽게 유효기간을 설정할 수 있게 해줍니다.

// 유효기간이 하루인 쿠키
document.cookie = "user=Choi; max-age=86400";

  1. secure

secure 옵션을 설정하면 HTTPS로 통신하는 경우에만 쿠키가 전송됩니다.

따라서, https://site.com에서 설정한 쿠키는 http://site.com에서 접근할 수 없습니다.

// https:// 로 통신하고 있다고 가정
document.cookie = "user=Choi; secure";

  1. httpOnly

httpOnly 옵션은 서버에서 Set-Cookie헤더를 이용해 쿠키를 설정할 때 지정할 수 있습니다. httpOnly 옵션을 설정하면 document.cookie를 통해 쿠키에 읽거나 쓸 수 없습니다.


레퍼런스

https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies
https://developer.mozilla.org/ko/docs/Web/API/Web_Storage_API
https://codepen.io/beaucarnes/pen/KmeRMx
https://ko.javascript.info/localstorage
https://ko.javascript.info/cookie
https://web.dev/i18n/ko/storage-for-the-web
https://blog.sessionstack.com/how-javascript-works-storage-engines-how-to-choose-the-proper-storage-api-da50879ef576
https://www.rdegges.com/2018/please-stop-using-local-storage
https://www.youtube.com/watch?v=NNuTV-gjlZQ&t=496s

profile
프론트엔드 공부하고 있습니다!

0개의 댓글