[JS] localStorage
예를 들어, 사용자가 일상 생활에서 할 일들을 까먹지 않고 메모하기 위해 이를 도와주는 todolist를 웹 사이트로 만들었다고 해보자. 이 웹 사이트 덕분에 웹 사이트 이용자들은 “오늘 장 볼 것들”, “오늘 할 일들” 등의 정보들을 해당 사이트에 기록할 수 있게 될 것이다. 그런데 한 가지 문제점이 있다. 만약 웹 사이트를 보여주고 있는 탭 또는 브라우저를 아예 꺼버린 후 다시 접속하면? 그 때에도 메모해놨던 데이터들이 그대로 화면에 뜰까? 그렇지 않을 것이다. 그러면 사용자가 해당 사이트를 끄고 나중에 접속하더라도 이전에 기록해놨던 메모들을 다시 웹 사이트에서 볼려면 어떻게 해야 할까? 한 가지 방법으로, 사용자 간의 구분을 위해 (A 사용자가 엉뚱하게 B 사용자의 메모를 볼 수 있게 해선 안되니깐) 회원 가입을 하게끔 하고, 그로부터 얻은 아이디, 패스워드 등의 정보를 서버 내 데이터베이스에 입력해둔다. 그러면 나중에 사용자가 특정 아이디와 패스워드를 입력하면 해당 사용자임을 인증할 수 있을 것이다. 그 후, 사용자가 쓴 메모도 데이터베이스에 저장해둔다. 그러면 사용자는 로그인만 하면 자신이 한 이전의 메모를 그대로 볼 수 있을 것이다.
음… 그런데… 그냥 단순한 메모를 위한 사이트인데, 굳이 이렇게까지 해야 할까? 굳이 서버를 구축하고 데이터베이스도 마련하고, 사용자 인증까지 해야할까? 만약 이렇게 하지 않고, 아예 메모 데이터들을 사용자 개인 컴퓨터에 저장하게끔 하고, 사용자가 해당 컴퓨터 내의 브라우저로 사이트에 접속했을 때, 사용자 개인 컴퓨터에 저장되어있던 데이터를 불러와도 되지 않을까? 그러면 결과적으로 사용자가 이전에 메모한 것들을 다시 웹 사이트에 불러올 수 있을 것이다. 굳이 거창하게 서버, 데이터베이스 구축까지 안 해도 되며, 로그인 기능이 없어도 사용자들 간의 구분을 할 수 있게 된다.
이 방법을 이용할 수 있는 방법으로 localStorage가 존재한다. 웹 스토리지 객체로, 브라우저 자체에 키-값 쌍의 데이터들을 저장할 수 있게 해주는 공간이라 보면 되겠다. 이를 이용하면 페이지 새로 고침, 브라우저를 끈 후 나중에 재실행 등의 작업을 하더라도 데이터가 그대로 보존되어 있어 이 데이터를 그대로 불러올 수 있다. 이 페이지에서는 localStorage에 대해 살펴보겠다. 참고로, 이와 비슷한 sessionStorage라는 것이 있는데, localStorage에 비해선 잘 안쓰인다고 한다. 그래서 이 문서에서도 가급적 localStorage를 중점적으로 설명할 것이다.
localStorage
앞서 설명했듯, localStorage는 브라우저 자체에 키-값 쌍의 데이터를 저장할 수 있는 웹 스토리지 객체이다. 사실 이와 비슷한 개념인 쿠키(cookie)도 있는데, 쿠키와의 차이점은 다음과 같다.
- 쿠키도 브라우저에 데이터를 저장할 수 있게 해주는 개념으로, 이 점에서는 localStorage와 비슷하지만, 쿠키는 클라이언트와 웹 서버 간의 통신이 가능하다. 이로 인해 쿠키는 클라이언트 식별 등의 인증에 주로 쓰인다고 한다. 반면, 웹 스토리지 객체는 그 데이터가 서버-클라이언트 간의 통신에 쓰이지 않는다. 즉, 서버와 통신을 하지 않는다.
- 이로 인해, 단순히 데이터를 브라우저에 저장하는 용도의 웹 스토리지 객체는 쿠키보다 더 많은 용량의 데이터들을 저장할 수 있다고 한다. 실제로 쿠키는 최대 4KB, localStorage는 최대 5MB의 데이터를 저장할 수 있다고 한다. (정확한 용량은 브라우저마다 다르다고 한다. 그래도 쿠키와 웹 스토리지 간 데이터 용량이 크게 차이난다는 사실은 변함없다) 이는 데이터를 서버와 통신하여 교환하면 그만큼 트래픽에 부담을 주기에, 통신을 위한 데이터의 용량을 크게 키우지 못하는 한계점에 의해 이러한 차이점이 발생하는 것이다.
한 편, 웹 스토리지 내 데이터들을 모든 사이트에서 접근하게 둔다면 어떨까? A 사이트에서만 사용되는 데이터를 만약 B 사이트에서도 무단으로 접근 가능하게 된다면 데이터가 의도치 않게 변형(오염)될 것이다. 그러면 A 사이트에서도 해당 데이터를 제대로 활용하지 못할 수 있다. 또한, A 사이트에서만 공개되길 원하는 데이터가 의도치 않게 B 사이트에서도 접근 가능해짐에 따라 보안 측면에서도 위험할 것이다. 다행히도, 웹 스토리지에서는 데이터 접근 시 아무 사이트에서나 접근하지 못하도록 도메인-프로토콜-포트로 정의되는 오리진(origin)을 기준으로 데이터 접근 권한을 제어한다. 즉, 도메인, 프로토콜, 포트 이 셋 중 하나라도 다르면 특정 데이터에 접근할 수 없는 구조이다.
오리진만 같으면, url 경로, 탭, 창이 다르더라도 동일한 데이터들에 접근할 수 있으며, 한쪽 창에서 데이터를 변경하면 다른 창에서 그 변경 사실이 업데이트된다.
자바스크립트에서 웹 스토리지 다루기
자바스크립트에서 이러한 웹 스토리지에 접근하기 위해 localStorage 객체를 이용한다. 우선, 해당 객체에서는 다음의 메서드 및 프로퍼티들을 제공한다.
메서드 또는 프로퍼티 | 설명 |
---|---|
setItem(key, value) | 키-값 쌍의 데이터를 입력, 저장시킨다. |
getItem(key) | 키에 해당하는 값을 반환. |
removeItem(key) | 특정 키를 입력하면 그 키와 키에 해당하는 값 모두를 삭제한다. |
clear() | 모든 데이터 삭제 |
key(index) | 인덱스에 해당하는 키를 반환 |
length | 저장된 총 키-값 쌍의 데이터 개수를 반환 |
키-값 쌍의 데이터를 받는다는 점, 그리고 키-값 쌍의 데이터에 대해 입력, 수정, 삭제 등의 행위를 할 수 있다는 점에서는 해시맵 자료구조와 동일해보인다. 그러나 한 가지 차이점은, key(index)
메서드에서 볼 수 있듯, 각각의 키에 인덱스를 부여하여 키만 따로 얻어올 수 있다는 것이다. 참고로 이러한 key(index)
메서드 덕분에, 모든 키-값 쌍 데이터를 순회할 수도 있다(자세한 내용은 후술).
다음은 localStorage 이용을 해보기 위해, 우선 html 문서를 만든 뒤, 해당 문서에서 자바스크립트 문서를 불러오도록 고안한 코드이다. 먼저, html 코드이다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="use-local-storage.js"></script>
</body>
</html>
다음은 use-local-storage.js 내 코드이다.
localStorage.setItem('nickName', 'james');
localStorage.setItem('yourNum', 12);
/*
alert(localStorage.getItem('nickName'));
alert(localStorage.getItem('yourNum'));
*/
// 모든 키-값 쌍을 for문을 이용하여 순회하면 더 쉽게 모든 데이터를 얻을 수 있음.
for(let i = 0; i < localStorage.length; i++) {
let key = localStorage.key(i);
alert(`${key}: ${localStorage.getItem(key)}`);
}
localStorage.setItem('nickName', 'john');
위 파일들을 vscode 에디터에서 “Live Server” 확장에서 제공하는 “Go Live” 버튼을 누름으로써 로컬 컴퓨터에서 해당 웹 페이지를 구동시켜보았다.
Go Live 버튼을 눌러 로컬 디바이스에서 웹 페이지를 구동시킨다.
다음은 웹 페이지에서의 결과물이다.
사진 1-1. 로컬 컴퓨터에서 구동시킨 웹 페이지 모습1
사진 1-2. 로컬 컴퓨터에서 구동시킨 웹 페이지 모습2
localStorage에 저장한 키-값 쌍이 잘 저장되었고, 또한 해당 데이터들을 얻어와 웹 페이지 화면에 잘 출력됨을 확인하였다.
한 편, 앞선 자바스크립트 코드에서 볼 수 있듯, localStorage내에 저장된 특정 오리진에 대한 모든 데이터들을 순회하려면 localStorage.length와 for문을 결합하여 인덱스 접근 방식으로 순회하면 된다.
한 편, localStorage에서의 키, 값은 모두 문자열이어야 한다. 다른 자료형을 이용하면 문자열로 자동 변환된다. 위 에제 코드에서도, yourNum 키에 해당하는 값을 숫자형으로 12를 대입하더라도, localStroage 상에서는 ‘12’와 같이 문자열로 저장되어 있을 것이다.
storage event
localStorage(sessionStorage 포함) 내의 데이터가 변경되었을 때 storage 이벤트가 발생된다. 따라서 localStorage 내 데이터가 업데이트되면 특정 기능을 수행하게끔 이벤트 핸들러로 다룰 수 있게 된다.
다음은 초기 데이터들을 입력한 후, 그 중 특정 데이터의 값을 변경하는 예제이다. 이 때, storage 이벤트의 핸들러를 생성하여, 변경된 데이터에 대한 정보를 웹 페이지에 보여주는 예제이다.
먼저 html 코드를 다음과 같이 작성하였다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script src="storage-event.js"></script>
</body>
</html>
해당 html 내에서 불러올 자바스크립트 코드를 다음과 같이 작성하였다.
// 기존에 이미 특정 데이터가 저장되어 있다면 새로운 환경에서의 테스트를 위해
// 이를 모두 삭제함.
localStorage.clear();
localStorage.setItem('nickName', 'james');
localStorage.setItem('yourNum', 12);
// window 객체에서 storage 이벤트를 처리함으로써,
// 웹 문서 전역에서 일어날 수 있는 storage 이벤트를 처리할 수 있음.
window = addEventListener('storage', (event) => {
// nickName 키와 그에 해당하는 값의 변경에만 관심있음.
if (event.key != 'nickName') {
return;
}
let message = `웹 스토리지 정보 갱신됨
갱신된 키 : ${event.key}
이전 값 : ${event.oldValue}
새 값 : ${event.newValue}`;
alert(message);
});
// 특정 키-값 쌍의 값이 변경됨.
localStorage.setItem('nickName', 'John');
그 후, 해당 html에서 앞선 예제와 같이 vscode 에디터의 “Go Live”를 클릭하여 로컬 서버를 연다. 그러면 처음에는 다음과 같이 빈 페이지 하나가 뜰 것이다.
사진 2-1.
여기서 새 탭을 생성한 후, 해당 탭의 url에 같은 주소를 기입하여 해당 페이지로 이동한다. 그러면 두 개의 탭이 하나의 같은 페이지를 참조하는 형태가 될 것이다. 이 때, 맨 처음에 웹 페이지를 띄웠던 탭으로 되돌아가면 다음의 알림창을 볼 수 있다.
사진 2-2.
localStorage에 접근하여 특정 데이터를 변경하면 storage 이벤트가 발생하고, 이를 처리하는 이벤트 핸들러를 설정하여 데이터가 변경되면 이 사실을 알림창에 띄우도록 하였기 때문에 위와 같은 결과를 얻을 수 있는 것이다.
한 편, storage event 객체에는 다음의 프로퍼티들이 존재한다.
- key : 변경된 키-값 쌍 데이터의 키. 만일 .clear()를 호출한 경우라면 null을 얻는다.
- oldValue : 변경된 데이터의 이전 값. 만약 데이터가 새롭게 추가된 경우라면 null을 반환.
- newValue : 변경된 데이터에서 새로 할당된 값. 만약 데이터가 삭제된 경우라면 null을 반환.
- url : 데이터 업데이트가 일어난 페이지의 url
- storageArea : 업데이트가 발생한 localStorage 또는 sessionStorage
References
[1] localStorage와 sessionStorage
This content is licensed under
CC BY-NC 4.0
댓글남기기