브라우저 별 로컬스토리지 사용법: 파이어폭스, 크롬, IE11


개요

이 문서에서는 로컬 스토리지 설명과 각 브라우저의 동작을 검증합니다.

로컬 스토리지는 데이터를 브라우저에 저장하는 구조입니다.


저장할 때 사이트마다 Key와 문자의 조합으로 데이터를 저장합니다.


사이트별 영역은 각각 독립적이며 다른 사이트에서 기록한 데이터를 조작할 수 없습니다.

또한 사이트마다 저장할 수 있는 한도는 제한됩니다. 그 구체적인 크기는 브라우저마다 다릅니다.


자세한 사양은 아래를 참조하세요.

https://html.spec.whatwg.org/multipage/webstorage.html#the-localstorage-attribute

구현 예시

아래에 로컬 스토리지의 사용 방법을 소개합니다. 파이어폭스, 크롬, 익스플로러11, 엣지.


로컬스토리지 API 사용 예제

localStorage 관련한 API 사용 예제를 소개합니다.

이 API는 처리가 완료될 때까지 제어할 수 없도록 동기 처리 됩니다.


지정된 키에 데이터를 저장

localStorage.setItem("KeyName","Data");


저장되는 데이터는 문자열에 불과합니다.

만약 객체를 저장할 경우, JSON을 사용하여 문자열로 변환하거나, 아래의 store.js 라이브러리를 사용합니다.


사이트마다 용량을 초과할 경우 예외가 발생합니다.

이때 발생하는 예외는 과거엔 브라우저마다 달랐지만, 글을 처음 작성한 2019년 11월 당시에 주요 브라우저는 QuotaExceededError가 발생합니다.



 브라우저 이름

 예외 이름

 FireFox 69.0.3

 QuotaExceededError

 Chrome 78

 QuotaExceededError

 IE11

 QuotaExceededError

 Microsoft Edge 44.18362.449.0

 QuotaExceededError



지정된 키 취득

console.log(localStorage.getItem("KeyName"))


존재하지 않는 키를 지정한 경우엔 null이 반환됩니다.


지정된 키 삭제

localStorage.removeItem("keyName")


존재하지 않는 키를 지정해도 에러가 발생하진 않습니다.


모든 키 삭제

localStorage.clear()


사이트에 등록된 모든 키를 삭제합니다.


등록된 모든 키 알아보기

var keys = [];

for (var i = 0; i < localStorage.length; ++i) {
  keys.push(localStorage.key(i));
}

window.alert(keys.join("\n"));


key 메소드를 사용하면 키 이름을 얻을 수 있습니다.

store.js 로컬 스토리지 용 라이브러리

store.js

https://github.com/marcuswestin/store.js


store.js는 로컬 스토리지 작업을 수행하는 MIT 라이센스 라이브러리입니다.

로컬 스토리지를 사용할 수 있으면 직접 사용하고, IE6, IE7 등은 userData를 사용하여 동일한 작업을 수행합니다.

이 라이브러리에 객체를 전달하면 JSON으로 변환하여 저장합니다.


storage 이벤트

setItem(), removeItem(), clear() 메소드가 실행되었을 때, storage 이벤트가 같은 사이트를 보고 있는 다른 창에 결과를 표시합니다.


다음에 그 이벤트를 얻는 예시입니다.


window.addEventListener("storage", function (event) {
  var data = 'key:' + event.key +
             ' oldValue:' + event.oldValue +
             ' newValue:' + event.newValue +
             ' url:' + event.url +
             ' storageArea:' + event.storageArea;
  console.log(event);
});


브라우저를 2개 열고 한쪽에서 SetItem 등의 함수를 호출하면, 다른 창에서 이벤트가 발생합니다.


브라우저 간의 동작 차이

검증 코드를 사용하여 각 브라우저의 로컬 스토리지 서비스에 어떤 차이가 있는지 확인합니다.


  • FireFox 69.0.3 + Windows10
  • Chrome 78 + Windows10
  • IE11 + Windows10
  • Microsoft Edge 44.18362.449.0 + Windows10



검증용 코드

아래의 사이트에 접속합니다. 크롬, 파이어폭스, 익스플로러, 엣지 공통 소스입니다.

http://needtec.sakura.ne.jp/release/storageTest.html


<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
  <title>Storage Sample</title>
</head>
<body>
<p>
  KEY:
  <input id="storeKey" type="text" value="testData"></input>
</p>
<p>
  DATA:<BR>
  <textarea id="storeMsg" col="40" row="10"></textarea>
</p>
<p>
  EVENT:<BR>
  <select id="eventLog" multiple="multiple"></select>
</p>
<button id="update">update</button>
<button id="reload">reload</button>
<button id="testObject">testObject</button>
<button id="delete">delete</button>
<button id="clear">clear</button>
<button id="keyList">keyList</button>
<p>
  Big Data:<BR>
  <input id="bigSize" type="text" value="5242880"></input>
  <button id="updateBigData">대용량 데이터 쓰기</button>
</p>
<script>
  reloadStorage();
  // 지정된 키 값 갱신
  document.getElementById('update').addEventListener('click', function() {
    let key = document.getElementById('storeKey').value;
    let contents = document.getElementById('storeMsg').value;
    localStorage.setItem(key, contents);
    console.log('localStorage.setItem(%s, %s)', key, contents);
  });

  // 스토리지 읽기
  function reloadStorage() {
    let key = document.getElementById('storeKey').value;
    let contents = localStorage.getItem(key);
    document.getElementById('storeMsg').value = contents;
    console.log('localStorage.getItem(%s) is %s', key, contents);
  }

  // 지정된 키 값을 불러오기
  document.getElementById('reload').addEventListener('click', function(){
    reloadStorage();
  });


  // 지정된 키 값 삭제
  document.getElementById('delete').addEventListener('click', function(){
    let key = document.getElementById('storeKey').value;
    localStorage.removeItem(key);
    console.log('localStorage.removeItem(%s)', key);
  });

  // 모두 삭제
  document.getElementById('clear').addEventListener('click', function(){
    localStorage.clear();
    console.log('localStorage.clear()');
  });

  // 키 목록
  document.getElementById('keyList').addEventListener('click', function(){
    let keys = [];
    for (var i = 0; i < localStorage.length; ++i) {
      keys.push(localStorage.key(i));
    }
    window.alert(keys.join("\n")); 
  });

  // 오브젝트로 쓰기
  document.getElementById('testObject').addEventListener('click', function(){
    let obj = {test:"123", value:123};
    localStorage.setItem('testObject', obj);
    console.log(localStorage.getItem('testObject'));
    window.alert(JSON.stringify(localStorage.getItem('testObject'))); 
    // 오브젝트는 무의미
    // [object Object]라는 문자열이 될 뿐
  });

  // 지정된 크기 데이터 생성
  document.getElementById('updateBigData').addEventListener('click', function(){
    try {
      let value = parseInt(document.getElementById('bigSize').value,10);
      let data = Array(value).join("x");
      let key = 'k';
      localStorage.clear();
      console.log('대량의 로컬스토리지 데이터 작성 key:%s size:%d', key, value);
      localStorage.setItem(key, data);
    } catch(e) {
      console.log(e);
      window.alert(e);
    }
  });

  // storage 이벤트
  window.addEventListener("storage", function (event) {
    let data = 'key:' + event.key +
               ' oldValue:' + event.oldValue +
               ' newValue:' + event.newValue +
               ' url:' + event.url +
               ' storageArea:' + JSON.stringify(event.storageArea);
    console.log('storage event : %o', event);
    let eventLog = document.getElementById('eventLog');
    let option = document.createElement("option");
    option.text = data;
    eventLog.appendChild(option);
  });

  // storagecommit 이벤트
  window.addEventListener("storagecommit", function (event) {
    console.log('storagecommit event : %o', event);
  });


</script>
</body>
</html>

FireFox 69.0.3 + Windows10 (파이어폭스 + 윈도우10)

저장 위치 :

C:\Users\사용자 이름\AppData\Roaming\Mozilla\Firefox\Profiles<profile folder>\webappsstore.sqlite

형식으로 다음과 같은 SQL에서 얻을 수 있습니다.


select * from webappsstore2;


이벤트 동작 :

  • 자신의 Window에서 수행한 작업 이벤트 결과는 자신의 Window에 표시되지 않음
  • setItem 인자가 이전 값과 같은 경우엔 이벤트가 발생하지 않음
  • removeItem에 존재하지 않는 키를 지정한 경우, 이벤트는 발생하지 않음
  • clear 후에 다시 클리어해도 이벤트는 발생하지 않음


저장 한계 :

키 이름을 "k"며 5242881 문자를 데이터로 저장한 경우 QuotaExceededError 예외가 발생합니다.


개발자 도구의 확인 방법 :

Storage 탭에서 Local Storage를 선택



사용자가 직접 로컬 스토리지 삭제 :

Options를 선택



Privacy&Security 탭에서 "Clear Data" 버튼 누름




즉시 사라집니다.


Private Windows 경우

  • 일반 모드로 기록한 내용은 읽을 수 없음
  • 쓰기 시 오류 발생
  • 같은 Private Window라도 쓴 내용을 다른 탭에서 읽을 수 없음
  • 브라우저를 종료하고 다시 Private Windows을 열어도 기록된 내용은 읽을 수 없음


※ 새 탭에서 열 때 동작은 다음과 같습니다.

①Private Window A에서 로컬 스토리지를 기록

②Private Window B를 새 탭에서 열기

→이 시점에서 ①의 내용은 가져올 수 없습니다.

③Private Window A에서 ①과 같은 키로 로컬 스토리지를 기록

④Private Window B에 이벤트가 발생. 이후 ③에서 기록한 내용을 취득

Chrome 78 + Windows10 (크롬 + 윈도우10)

저장 위치 :

C:\Users\사용자 이름\AppData\Local\Google\Chrome\User Data\Default\Local Storage\leveldb


LevelDB 에서 기록합니다.


공부하면 이해할 수 있지만, 솔직히 저는 잘 모르겠습니다.

https://scrapbox.io/mima3/leveldb


이벤트 동작 :

  • 자신의 Window에서 수행한 작업 이벤트 결과는 자신의 Window에 표시되지 않음
  • setItem 인자가 이전 값과 같은 경우엔 이벤트가 발생하지 않음
  • removeItem에 존재하지 않는 키를 지정한 경우, 이벤트는 발생하지 않음
  • clear 후에 다시 클리어해도 이벤트는 발생하지 않음


저장 한계 :

키 이름을 "k"며 5242881 문자를 데이터로 저장한 경우 QuotaExceededError 예외가 발생합니다.


개발자 도구의 확인 방법 :

Application 탭에서 Storage> Local Storage를 선택합니다.



사용자가 로컬 스토리지 제거하기 :

설정 ⇒ 고급 ⇒ 인터넷 사용 기록 삭제보다는 "쿠키 및 기타 사이트 데이터"를 삭제합니다.


시크릿 모드인 경우

  • 일반 모드로 기록한 내용은 읽을 수 없음
  • 쓰기 시 오류 발생
  • 같은 Private Window라도 쓴 내용을 다른 탭에서 읽을 수 없음
  • 브라우저를 종료하고 다시 Private Windows를 열어도 기록된 내용은 읽을 수 없음


Internet Explore 11 (익스플로러 + 보나 마나 윈도우)

저장 위치 :

C:\Users\사용자 이름\AppData\LocalLow\Microsoft\Internet Explorer\DOMStore\0FOJP942

XML 형식입니다.


이벤트 동작 :

  • 자신의 Window에서 수행한 작업 이벤트 결과는 자신의 Window에 표시되지 않음
  • setItem 인자가 이전 값과 같은 경우엔 이벤트가 발생하지 않음
  • removeItem에 존재하지 않는 키를 지정한 경우, 이벤트는 발생하지 않음
  • clear 후에 다시 클리어해도 이벤트는 발생하지 않음
  • XML에 데이터를 쓸 때, 작업을 수행한 창에 storagecommit 이벤트가 발생됩니다. 이 이벤트의 취득 예시는 다음과 같습니다.


window.addEventListener("storagecommit", function (event) {
  console.log("storagecommit");
  console.log(event);
});


대량의 데이터를 setItem할 때 동작이 불안정합니다.


예 :

  • 30000 문자를 setItem한다. ⇒ storage 이벤트가 발생
  • 다시 30000 문자를 setItem한다. ⇒ storage 이벤트가 발생하지 않음
  • 일단 키를 삭제한다. ⇒ storage 이벤트가 발생
  • 30000 문자를 setItem한다. ⇒storage 이벤트가 발생


저장 한계 :

키 이름을 "k"며 5242881 문자를 데이터로 저장한 경우 QuotaExceededError 예외가 발생합니다.


개발자 도구에서 확인 방법 :

없음


사용자가 로컬 스토리지의 삭제 방법 :

옵션 ⇒ "일반"탭 ⇒ 검색 기록 삭제에서 "쿠키 및 Web 사이트 데이터"를 선택하여 삭제 후 IE를 다시 시작합니다.

https://docs.microsoft.com/ko-kr/previous-versions/windows/desktop/legacy/bg142799(v=vs.85)?redirectedfrom=MSDN

Microsoft Edge 44.18362.449.0 + Windows10 (엣지 + 윈도우10)

저장 위치

C:\Users\사용자 이름\AppData\Local\Packages\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\AC#!001\MicrosoftEdge\User\Default\DOMStore\E2WN2O9U


XML 파일에 저장되어 있습니다.


이벤트 동작 :

  • 자신의 Window에서 수행한 작업 이벤트 결과는 자신의 Window에 표시되지 않음
  • setItem 인자가 이전 값과 같은 경우엔 이벤트가 발생하지 않음
  • removeItem에 존재하지 않는 키를 지정한 경우, 이벤트는 발생하지 않음
  • clear 후에 다시 클리어해도 이벤트는 발생하지 않음


저장 한계 :

키 이름을 "k"며 5242881 문자를 데이터로 저장한 경우 QuotaExceededError 예외가 발생합니다.


개발자 도구 확인 방법 :

저장소탭을 선택합니다.



사용자가 로컬 스토리지 삭제하는 방법 :



InPrivate 브라우징 경우

  • 일반 모드에서 기록한 내용을 못 읽음
  • 쓰기 시 오류 발생
  • 같은 InPrivate 브라우징의 다른 탭에서도 기록한 내용을 읽을 수 없음
  • 다른 페이지로 전환할 때 기록한 내용을 읽을 수 없음
  • 브라우저를 종료하고 다시 InPrivate 브라우징으로 열면 이전 기록은 읽을 수 없음


정리

로컬 스토리지를 사용함으로써 보다 쉽게 클라이언트 사이드에 정보를 유지할 수 있습니다.

최근 주요 브라우저에선 이 작업이 비슷해지고 있습니다. (마이크로 소프트 MS 계열 제외한 파이어폭스, 크롬, 사파리 등)


store.js를 이용하면, 브라우저간 호환은 더 쉽습니다.


하지만 대용량 데이터 처리엔 적합하지 않은데, 그 이유는 두 가지입니다.

  1. 동기화 처리를 위한 대용량 데이터 처리 시, 멈춰버립니다
  2. 사이트마다 스토리지 상한이 정해져 있는데, 고작 몇 MB입니다.


스토리지의 상한은 「모른다」로 처리하는 것이 좋습니다.


사용자가 브라우저의 기능에 로컬 스토리지를 백업하는 방법이 없으므로, 사라지면 안되는 자료만 저장해야 합니다. 또한, 중요한 정보라면 내보내기 기능이 필요할 것입니다.


IE11을 사용하면 스토리지의 이벤트 사용은 피하는 것이 좋습니다.


IE11과 Edge. sinon.js 등에서 localStorage.setItem 등의 Mock과 Fake를 작성할 수 없습니다. localStorage.setItem으로 설정된 값을 변경할 수 없기 때문입니다. 또한 다음의 방법으로 LocalStorage를 비활성화하고 있을 수 있습니다.



댓글(0)

Designed by JB FACTORY