[HTML5] WebStorage

HTML/CSS 2010. 12. 29. 18:01



참고문서: http://dev.w3.org/html5/webstorage



쉽게 말해서 클라이언트에 데이터를 저장할 수 있는 것이다.

기존에도 쿠키를 이용해서 저장하거나 할 수 있지만 쿠키는 아래와 같은 단점이 있다.

1. 모든 HTTP request에 다 따라붙어서 쓸 데 없는 트래픽 증가를 유발.
2. 모든 웹서비스가 SSL이 아닌 한 암호화되지 않은 상태로 네트워크로 돌아다니므로 보안에 취약.
3. 최대 사이즈가 4kb (트래픽 증가에는 충분하고 실제로 뭘 좀 해보기엔 턱 없이 부족한 애매한 크기)

위와 같은 단점을 보완하기 위해 나온 것이 WebStorage.
아래와 같은 개선사항이 반영되었다.

1. 저장공간 확대 (5Mb)
2. 클라이언트에서만 사용하고 HTTP request에 자동으로 따라붙지 않도록.
3. 리프레쉬 이후에도 데이터가 그대로 남도록.




WebStorage는 key-value 형태로 저장된다.
key는 문자열이고,
value는 JavaScript에서 지원하는 여러 데이터를 저장할 수 있지만 기본적으로 문자열만 된다고 보고,
만약 integer나 float 등을 저장했다면 꺼내쓸 때 parseInt(), parseFloat() 등으로 처리해주는 것이 좋을 듯.



다음은 WebStorage의 인터페이스다.
interface Storage {
    // properties   
    readonly attribute unsigned long length;
    // methods
    getter DOMString key(in unsigned long index);
    getter any getItem(in DOMString key);
    setter creator void setItem(in DOMString key, in any data);
    deleter void removeItem(in DOMString key);
    void clear();
};


length - storage에 저장되어 있는 아이템 갯수.
key() - index에 해당하는 키이름을 반환. index는 0~(length-1) 사이의 값을 지니며, 해당 범위를 벗어나면 null을 반환.
getItem() - key에 해당하는 값을 반환. 없는 값을 요청할 경우 예외를 발생시키는 대신 그냥 null을 반환
setItem() - key 인덱스에 data를 저장. 만약 값이 이미 있는 경우에는 덮어 씀.
removeItem() - key에 해당하는 값을 삭제. 만약 없는 값을 지우려 하면 아무 동작도 수행하지 않음.
clear() - 모든 데이터를 삭제.



WebStorage 사용시 getItem, setItem을 사용하는 대신 그냥 연관배열 형태로도 사용가능.
// method 호출 형태
var foo = localStorage.getItem("bar");
// 연관배열 형태
var foo = localStorage["bar"];







WebStorage는 실제 값의 변화가 있을 때에만 Event를 발생시킨다.
예를 들어 setItem(), removeItem(), clear() 등은 일반적으로 호출시 이벤트를 발생시키지만,
setItem()을 통해 동일한 값을 덮어씌우거나, 아무 데이터가 없는 상태에서 clear()를 호출하면 이벤트는 발생하지 않는다.

브라우저마다 이빈트 핸들러 구현방식이 달라서 아래처럼 해주는 것이 좋다.
// 아래처럼 이벤트를 붙이고
if (window.addEventListener) window.addEventListener("storage", handle_storage, false);
else window.attachEvent("onstorage", handle_storage);

// 아래처럼 핸들러를 구현한다.
function handle_storage(e)
{
    if (!e) e = window.event;
    ...
    ...
}


다음은 StorageEvent의 인터페이스
interface StorageEvent : Event {
    readonly attribute DOMString key;
    readonly attribute any oldValue;
    readonly attribute any newValue;
    readonly attribute DOMString url;
    readonly attribute Storage storageArea;
    void initStorageEvent(in DOMString typeArg, in boolean canBubbleArg, in boolean cancelableArg, in DOMString keyArg, in any oldValueArg, in any newValueArg, in DOMString urlArg, in Storage storageAreaArg);
};


key [string] - 추가, 삭제 혹은 수정되는 키이름
oldValue [any] - 덮어씌워질 경우에는 덮어씌워지기 이전의 데이터이고, 새로운 데이터가 추가된다면 null
newValue [any] - 새로운 데이터. 삭제 이벤트의 경우에는 null
url [string] - 해당 이벤트를 발생시킨 페이지의 url

참고로 storage event는 callback에서 중지시킬 수가 없다. 그러므로 원천적인 hook이 불가능하다.





WebStorage는 물리적으로 해당 하드웨어에 접근할 수 있다면 읽기, 수정 등이 가능하다.
하지만 same-origin restriction에 의거하여 다른 도메인에서 또 다른 도메인의 WebStorage에는 접근할 수가 없다.
뭐 여하튼 보안에 관계된 데이터는 WebStorage에 저장하지 않는 것이 좋을 듯.





다음은 localStorage를 이용하여 데이터를 저장, 삭제, 수정하는 기본 예제이다.

<!DOCTYPE HTML>
<html>

<head>
<script>
// 데이터 삭제
function del()
{
    localStorage.removeItem(keylist.options[keylist.selectedIndex].value);
    listAll();
}

// 전체 삭제
function deleteAll()
{
    if (confirm("정말 전부 삭제하시겠습니까?")) {
        localStorage.clear();
        listAll();
    }
}

// 데이터 추가
function add()
{
    if (key.value == "") {
        alert('키를 입력해주세요.');
        key.focus();
        return;
    }

    if (val.value == "") {
        alert('값을 입력해주세요.');
        val.focus();
        return;
    }

    localStorage.setItem(key.value, val.value);
    listAll();
}

// 전체리스트
function listAll()
{
    // UI 초기화
    key.value = "";
    val.value = "";
    keylist.selectedIndex = 0;

    // 갯수
    len.innerHTML = localStorage.length;

    // 데이터
    keylist.innerHTML = "";
    datalist.innerHTML = "<b>localStorage</b><br />";
    for (var i in localStorage) {
        datalist.innerHTML += i+" ===> "+localStorage[i]+"<br />";
        keylist.innerHTML  += "<option value='"+i+"'>"+i+"</option>";
    }
}

// 초기화
var len = datalist = key = val = keylist = null;
window.onload = function() {
    len       = document.getElementById('len');
    datalist = document.getElementById('datalist');
    key      = document.getElementById('key');
    val       = document.getElementById('val');
    keylist  = document.getElementById('keylist');

    listAll();
}
</script>
</head>

<body>

<div>
    저장된 데이터는 <span id="len"></span>개 입니다.
    <br /><br /><br />
    <div id="datalist"></div>
    <hr />
    <br />
    key: <input type="text" id="key" />
    &nbsp;
    val: <input type="text" id="val" />&nbsp;<input type="button" value="저장" onclick="add();" />
    <br />
    <select id="keylist">
    </select>
    &nbsp;
    <input type="button" value="삭제" onclick="del();" />
    <br />
    <input type="button" value="전체삭제" onclick="deleteAll();" />
</div>

</body>
</html>



위의 예제를 구동시키면서 구글 크롬의 '개발자도구'를 확인해보면 Storage 탭에 저장한 데이터가 있는 것을 확인할 수 있다. (파폭은 내가 안써서 잘 모름. 파이어버그에 있을려나)



Posted by bloodguy
,