세션스토리지(sessionStorage), 로컬스토리지(localStorage)로 구성된 웹 스토리지는 이제 너무 익숙합니다.
다루기 힘들었던 쿠키와는 다르게 클라이언트 저장소로 사용 용도를 명확히 하고 더 나은 사용성으로 이미 우리의 친구가 됐죠.
프론트엔드 개발자가 자주 다루는 로컬 스토리지는 이런 것들을 할 수 있습니다.
- storage.length
- storage.key(n)
- value = storage.getItem(key)
- value = sotrage[key]
- storage.setItem(key, value)
- storage[key] = value
- storage.removeItem(key)
- delete storage[key]
- storage.clear()
API가 잘 설계되어 있어서 이름만 보고 어떻게 동작하는지 금방 알 수 있습니다.
그런데 그거 아세요?
스토리지에 이벤트를 걸 수도 있다는 사실을요.
바로 웹 스토리지 이벤트(web storage event)입니다.
왜 쓸까?
스펙상으로는 아래와 같은 내용을 이벤트로 받을 수 있어요.
- setItem()으로 아이템을 업데이트한 경우
- removeItem()으로 아이템을 지운 경우
- clear()로 모든 것을 지운 경우
즉, 로컬 스토리지에 생기는 변화를 감지해 특정 작업을 수행할 수 있습니다.
동일한 탭 혹은 동일한 윈도우 안에서는 이벤트가 발생하지 않고요. 서로 다른 탭, 윈도우에서만 이벤트가 발생합니다.
어떻게 쓸까?
이벤트를 거는 방법은 간단합니다.
window.addEventListener('storage', () => {
console.log(JSON.parse(window.localStorage.getItem('sampleList')));
});
window.onstorage = () => {
console.log(JSON.parse(window.localStorage.getItem('sampleList')));
};
우리가 로컬 스토리지를 사용할때 localStorage라는 싱글톤 객체를 이용하잖아요. 그러니까
localStorage.addEventListener('storage', ...);
이렇게 인스턴스에 직접 이벤트를 거는 사용법이 더 직관적이고 앞으로 확장이 더 용이하지 않을까 생각해 봤어요. storage
라는 이벤트가 있다길래 앞뒤 안 가리고 저렇게 시도해 봤다가 안됐었거든요. 아마 저 말고도 몇 분 있을실 것 같아요. :)
StorageEvent 객체
다른 이벤트와 동일하게 스토리지 이벤트도 이벤트 객체를 받아서 정보를 얻을 수 있는데요. Event
를 상속받는 StorageEvent
는 아래와 같은 추가 정보를 갖고 있습니다.
- key: 변경된 키값
- newValue: 변경된 값
- oldValue: 변경되기 직전의 값
- storage: 변경된 스토리지(localStorage 혹은 sessionStroage)
- url: 변경된 대상의 url
핸들러에서 일반 이밴트 객체처럼 사용할 수 있어요
window.addEventListener('storage', (ev) => {
console.log(ev.key);
});
localStroage.setItem('myData', 'data1');
어디에 쓸까?
스토리지 이벤트는 다양하게 응용될 수 있을 것 같아요.
장바구니같이 쇼핑 중에 자주 사용되는 UI는 여러 탭에 열릴 가능성이 큰데요. 장바구니의 제품들을 주문해서 장바구니가 비워진 경우 쉽게 모든 탭에서 장바구니를 업데이트할 수 있을 것 같아요. 진입 시 업데이트나 폴링을 이용하는 것보다 UX에 더 좋겠죠.
다중 탭에서 서비스를 사용하는 유저가 한 탭에서 로그아웃을 시도한 경우 이벤트를 활용해 다른 탭도 동시에 로그아웃 상태로 바꾸는 구현도 할 수 있고요. 링크드 인이 이 방식을 사용하는 것 같더군요.
비슷한 맥락으로 탭 간의 실시간 동기화를 구현할 수 있을 것 같습니다. 이렇게 보니 탭 간의 이벤트 기반 메시지 교환 도구로 활용될 수 있겠네요.