티스토리 뷰

웹 스토리지

웹 스토리지는 HTML5에 정의된 API였지만, 현재는 독립적인 표준이 되었다. 해당 표준은 여전히 초안 상태이지만, IE8을 포함한 모든 최신 브라우저에서 부분적으로 구현하고 있다. 이 API는 본질적으로 문자열 키와 값을 대응시킨 영속적 연결 배열인 로컬 스토리지와 세션 스토리지 객체로 구성되어 있다. 웹 스토리지는 매우 사용하기 쉽고, 너무 크지 않은 대량의 데이터를 저장하기에 적합하면, 구형 브라우저에서는 지원하지 않지만 모든 최신 브라우저에서 사용할 수 있다.


- localStorage : 로컬에 origin 별로 지속되는 스토리지

- sessionStorage : 현재 세션 동안만 유지되는 스토리지

: 이러한 스토리지가 주어지게 된 이유는 기존의 쿠키에 대한 제약들을 해소하고 조금 더 다양하고 클리이언트에 많은 기능들을 넣고자 하였기 때문에 HTML5에 새로운 기능인 localStorage와 sessionStorage를 추가한 것이다. 

// 웹 스토리지와 쿠키 비교

웹 스토리지 

쿠키 

약 5MB까지 저장가능 

4KB만 저장가능 

서버로 전송할 필요 없음 

매번 HTTP 요청 해더에 붙여 전송(트랙픽 낭비) 

상대적으로 보안에 안전 

보안에 취약 

개수 제한 없음 

20개 정도로 개수 제한 



이에 대한 문제점을 보완하기 위하여 용량을 확장하고, 서버로는 전달이 되지 않고 브라우져 로컬에만 저장되며, 보안도 보장할 수 있도록 새로운 표준을 정의한 것이 바로 웹 스토리지이다. 이미 대부분의 브라우져는 이러한 스토리지를 지원해주고 있으므로 아직 쿠키를 사용하고 있는 사이트가 있다면 이제는 기술 이전을 해야 할 시기가 왓다고 본다.


// 저장된 값을 가져온다.

var name = localStorage.username;

// 배열과 표기법이 동등하다.

name = localStorage["username"];

if(!name)    {

// 사용자에게 질문한다.

name = prompt("What is your name?");

// 사용자의 응답을 저장한다.

localStorage.username = name;

}


// 저장된 모든 이름/값 쌍을 순회한다.

// 저장된 데이터명을 탐색한다.

for(var name in localStorage)    {

// 각 데이터의 값을 가져온다.

var value = localStorage[name];

}


// 숫자형의 데이터를 저장하면, 자동으로 문자열 타입으로 변환된다.

// 해당 데이터를 가져올 때에는, 본래의 타입으로 해석해야 함을 잊지 말자.

localStorage.x = 10;

var x = parseInt(localStorage.x);

// 날짜 데이터를 저장할 때는 문자열로 변환하고, 가져올 때는 Date 타입으로 변환한다.

localStorage.lastRead = (new Date()).toUTCString();


var lastRead = new Date(Date.parse(localStorage.lastRead));

// JSON은 어떠한 자료구조도 인코딩하기 편리하게 해준다.

localStorage.data = JSON.strigify(data);    // 인코딩하여 저장한다.

var data = JSON.parse(localStorage.data);    // 디코딩해서 가져온다.


웹 스트로지 생명주기와 범위

로컬 스토리지와 세션 스토리지는 저장된 데이터의 생명주기와 범위에 차이가 있다. 로컬 스토리지를 통해 저장된 데이터는 만료기한이 없고, 웹 애플리케이션이 삭제되기 전이나 사용자가 브라우저의 특정 인터페이스를 통해 삭제하기전까지는 사용자의 컴퓨터에 존재하므로 영구적으로 저장된다고 할 수 있다.

// 웹 스토리지의 범위는 문서의 출처(도메인)에 국한된다. 문서의 출처는 프로토콜과 호스트명, 프트 등에 의해 저으이되므로 다음 각 URL들은 출처가 모드 다르다.

http://www.example.com    // 프로토콜 : http, 호스트명 : www.example.com

https://www.example.com    // 프로토콜명이 다름

http://static.example.com    // 호스트명이 다름

http://www.example.com:8000    // 포트가 다름


* Session Storage

- 브라우저(세션)를 종료하면 데이터가 사라진다.

- 도메인마다 따로 생성된다.

- 윈도우(window 객체)와 같은 유효범위와 생존기간을 가진다. (같은 도메인이라도 윈도우마다 따로 생성된다.)

- 윈도우 복제로 생성된 경우, 스크립트를 이용해 새 창을 연 경우 같은 값을 가진 세션 스토리지가 '복제'된다.

- 새로 생성된 윈도우와 기존 위도우의 세션 스토리지는 서로 영향을 주지 않는다.

* Local Storage

- 브라우저를 껏다가 켜도 값이 유지된다.

- 도메인마다 따로 생성된다.

- 지속기간에 제한이 없다. 사용자가 명시적으로 지우지 않는 한 영구적으로 저장된다.

- 도메인(문서의 출처)이 다르면 서로의 로컬 스토리지에 접근할 수 없다. 

- 같은 도메인, 예를 들면 coute.me에 소속된 웹페이지는 모두 같은 로컬 스토리지를 가진다.( 접근한다.)

- Cooke를 이용한 사이트 고유 설정 정보등을 대신하기에 적당하다.


// 세션과 로컬의 차이점은 지속성(보존)을 가지기 때문에 여러 창을 켜도 같은 도메인이라면, 로컬 스토리지는 같은 스토리지를 사용하는 것입니다. 

// 세션 스토리지는 각 세션마다 새로운 스토리지를 사용하고 폐기합니다.


웹 스토리지 지원 여부 검사

지원하는 브라우저 : Internet Explorer 8이상, Firefox, Opera, Chrome, Safari

if( ('localStorage' in window) && window['localStorage'] !== null )    {

// 지원할 때 코드

} else {

// 지원하지 않을 때 코드(예: 지원하지 않음 오류처리 등)

}


웹 스토리지 API

메소드 

설명 

length 

스토리지에 저장된 데이터의 수를 반환 

key(index) 

지정된 인덱스의 키를 반환하고 키가 없다면 null 반환 

getItem(key) 

지정된 키에 대응하는 데이터를 반환 

setItem(key, data) 

지정된 키로 스토리지에 데이터를 저장 

removeItem(key) 

지정된 키에 대응하는 데이터를 삭제 

clear() 

모든 데이터를 스토리지에서 삭제 



웹 스토리지 이벤트

setItem, removeItem, clear 함수가 호출이 될 때 정상 처리되면, 다른 모든 위도우에 같은 localStorage를 참조하고 있는 Document에 이벤트를 발생시킨다. 즉, localStorage를 변경하면 현재에 있는 웹 페이지에서는 알림이 가지 않고, 다른 탭이나 새로운 청에서 같은 localStorage를 사용하고 있으면 해당 document에 이벤트를 발생시킨다고 되어 있다.

// 이벤트 객체의 프로퍼티

key : 값이 변경된 키 값. clear()메서드가 호출되었을 때는 null이다.

newValue : 새로운 값 또는 removeItem()이 호출되었을 경우 null이다.

oldValue : 이전 값. 새 데이터가 추가되었을 경우에는 null이다.

storageArea : 변경이 일어난 Storage 객체(Window 객체)

url : 변경이 일어난 URL


<body>

    <input type="text" id="text" />

    <button id="clear">Clear</button>

    <div id="log"></div>

</body>

<script>

(function () {

    var text = localStorage.getItem("inputLog") || "",

        divLog = document.getElementById("log"),

        inputText = document.getElementById("text"),

        buttonClear = document.getElementById("clear");

    if (text) {

        divLog.innerHTML = text;

    }

    inputText.addEventListener("change", function () {

        text += inputText.value + "<br />";

        divLog.innerHTML = text;

        localStorage.setItem("inputLog", text);

        inputText.value = "";

    });

    buttonClear.addEventListener("click", function () {

        localStorage.clear();

    })

    window.onstorage = function (e) {

        console.log("Storage event has occured");

        console.log(e);

    };

}());

</script>


<body onload="showAll()">

<h1>로컬 스토리지 뷰어</h1>

키: <input id="k" type="text">   값: <input id="v" type="text">

<button onclick="save()">저장</button>

<button onclick="remove()">삭제</button>

<button onclick="window.open(location.href);">윈도우 생성</button>

<hr>

<select id="entries" size=5 onchange="onEntrySelected()"> 

</select>

<button onclick="showAll()">다시 표시</button>

<script type="text/javascript">

var key = document.getElementById("k");

var value = document.getElementById("v");

var entries = document.getElementById("entries");


// 스토리지에 변경이 있으면 목록을 다시 표시함

window.addEventListener("storage", showAll, false);


// 스토리지 내용 모두 표시

function showAll() 

{

// 목록 clear

entries.innerHTML = "";


// 루프, 스토리지 내용 확인

for ( var i = 0; i < localStorage.length ; i++ ) 

{

var k = localStorage.key(i);

entries.options[entries.options.length] = new Option(k + ":" + localStorage[k], k);

}

}


// 스토리지에 저장

function save() 

{

localStorage[key.value] = value.value;

}


// 스토리지로부터 값을 삭제

function remove()

{

delete localStorage[key.value];

}


// 선택된 엔트리를 텍스트 필드에 표시

function onEntrySelected() 

{

var selectedOption = entries.options[entries.selectedIndex];

key.value = selectedOption.value;

value.value = localStorage[selectedOption.value];

}

</script>

</body>


보안

"같은 도메인의 서로 다른 디렉토리"의 공유서버 환경에서 서비스를 제공하는 경우에는 절대로 민감한 스토리지에 저장해서는 안 될 것이라고 이미 표준에서 부터 권장하고 있다. 이해하기 쉽게 예를 들면, http://blog.naver.com/asdf 에서 사용하고 있는 localStorage를 사용하는 사이트와 http://blog.naver.com/qwer 에서 사용하고 있는 localStorage는 결국 http://blog.naver.com의 도메인이 같기 때문에 스토리지가 공유된다는 내용이다.


그래도 해결되지 않은 문제점들..

웹 스토리지는 쿠키의 다양한 담점들을 극복하기 위하여 나왔기 때문에 쿠키가 있었던 거의 모든 중요한 단점들은 해결이 되었다. 하지만 쿠키에서도 있었던 몇 가지 문제들을 웹 스토리지에서도 그대로 가지고 있기 때문에 주의하면 좋은 부분들도 있다. 

첫 번째로는 브라우져간 스토리지 공유가 되지 않는다는 점이다. 이 부분은 서로 다른 컴퓨터라는 문제 뿐만 아니라 같은 컴퓨터 안의 다른 브라우져에서라도 스토리지가 공유되지 않고 브라우져들이 독자적으로 스토리지를 관리하기 때문에 항상 같은 내용을 보유하고 있어야하는 경우에는 스토리지를 사용하는 것이 아니라 서버에서 해당 내용을 관리하는 것이 좋다. 

두 번째로 고려해야 할 점은 바로 최근 브라우져들이 지원하고 있는 "Private 모드"이다. Private모드에서는 스토리지가 동작은 하나 일반적으로 Private모드의 세션이 끝나고 나면 관련 스토리지는 전부다 지워지게 된다. 따라서 사용자가 변경한 내용에 대해서 Private 모드임에도 계속 유지해야 하는 내용 역시 서버에서 관리하는 것이 좋다.


웹 스토리지를 사용하기 좋은 대표적인 예

- '오늘 하루 열지 않기'

- sesstionStorage를 활용해서 사용자가 '입력폼'을 입력하다가 페이지에서 벗어난 경우 백업/복구

- 글쓰기를 하다가 사용자가 창을 벗어난 경우 관련 작성하던 내용 백업/복구용

- 웹서버에 필수적으로 접근해야 하는 캐쉬용(캐쉬로 먼저 서비스 제공, 차후에 업데이트)

- 웹페이지의 개인화 설정들에 대한 저장과 제공(캐쉬로 활용)

- 현재 읽은 글의 히스토리 저장(카운팅, 읽은글 표시 등으로 활용)

- Canvas나 이미지에 대한 임시 저장 기능(base64로 변환)

- 웹페이지간 정보 전달(웹서버를 경유하지 않고 정보 로컬에 유지)

- 중요 CSS 저장용(참조: https://speakerdeck.com/patrickhamann/css-and-the-critical-path-cssconfeu-september-2014) 

/*

위의 경우들을 보면 굳이 동작하지 않아도 치명적이지 않은 기능들이다. 그리고 굳이 다른 브라우져/컴퓨터와 공유되지 않아도 문제 없거나 웹서버에서 쉽게 불러들일 수 있는 내용들이다. 이렇게 localStorage는 나름 주목을 할만한 기능이라고 생각할수도 있지만, 로컬이라는 한계 때문에 결국은 쿠키의 확장형 기능들을 제공하는 것이 적합하다고 생각한다. 물론 위의 예 중 마지막인 웹피잊간 정보 전달을 하는 경우 비지니스 로직으로 활용하는 것이 아주 나쁜것만은 아니기는 하지만 일단 sessionStorage로 사용할 것을 권장하고 전체적인 페이지의 흐름에 대해서 면밀히 검토하는 것이 좋다고 생각한다.

*/





'javascript > 클라이언트 스토리지' 카테고리의 다른 글

오프라인 웹 어플리케이션  (0) 2016.11.30
Indexed Database  (0) 2016.11.28
Web SQL Database  (0) 2016.11.28
웹 스토리지  (0) 2016.11.27
댓글
댓글쓰기 폼