IndexDB (1) : 간단한 개념을 알아보고 사용해보자
IndexedDB는 파일이나 블롭 등 많은 양의 구조화된 데이터를 클라이언트에 저장하기 위한 로우 레벨 API입니다. IndexedDB API는 인덱스를 사용해 데이터를 고성능으로 탐색할 수 있습니다. Web Storage(localStorage나 sessionStorage)는 적은 양의 데이터를 저장하는데 유용하지만 많은 양의 구조화된 데이터에는 적합하지 않은데, 이런 상황에서 IndexedDB를 사용할 수 있습니다.
- https://developer.mozilla.org/ko/docs/Web/API/IndexedDB_API
결국 Web Storage보다 많은 양의 데이터를 저장하는데 더 적합한 저장소라는 것이다. 단순히 get, set만 지원하는 것이 아니라 좀 더 DB스럽게 사용할 수 있고 용량도 더 많다.
Web Storage는 간편하지만 기능이 많다고 할 수는 없다. 좀 더 강력한 기능을 위해 google web.dev의 storage for web의 설명에 따르면 다음과 같은 저장소를 사용하도록 추천하고 있다.
- 네트워크 요청을 통해 받아온 정보를 캐싱하기 위해서는, use the Cache Storage API (part of service workers).
- 다른 경우에는, use IndexedDB (with a promises wrapper).
IndexDB의 특성들
(https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Basic_Terminology)
IndexedDB는 많은 양의 데이터를 저장하는 애플리케이션이지만 작동을 위해 지속적인 인터넷 연결이 필요하지 않은 애플리케이션에 적합하다. 예로 들자면, 할 일이 2만개가 되는 앱은 굳이 서버와 통신할 이유가 없고 데이터를 클라이언트 단에서만 저장하면 된다.
클라이언트 단이라고 하면 정확히 어디에 저장되는건가?
Chrome 기본 경로라는 가정 하에, 다음과 같은 경로에 저장된다.
%USERPROFILE%\AppData\Local\Google\Chrome\User Data\Default\IndexedDB
/Users/[USERNAME]/Library/Application Support/Google/Chrome/Default/IndexedDB/
기본적인 특성들은 무엇인가?
- 키-밸류 값으로 저장되고 가져온다.
- 빠른 검색과 정렬을 위해 개체의 속성을 사용하는 인덱스를 만들 수 있다. (WOW 이걸 웹에서?)
- IndexedDB는 트랜잭션 데이터베이스 모델을 기반으로 한다.
- The IndexedDB API is mostly asynchronous
- Full Text Searching 없음. (너무 당연한 거 아닌가;;)
- SQL의 Like 문 류의 기능 없음.
- 브라우저 설정에서 지우겠다고 선택하는 경우 (종종 브라우저 히스토리 지울 때 이것 저것 체크하는데 그 옵션인가 보다)
- 비공개 브라우저에서는 브라우저가 종료되면 IndexDB도 날아감
- 데이터가 손상되었을 때 (정확히 어떻게 손상되었을 때인지는 모르겠음)
- 컴퓨터 하드 드라이브 용량이 다 찼을 때
IndexDB를 사용하는 방법
Cursor, Index, TX 등 되게 많은 개념이 있어서 후딱 끝낼 수 없는 수준이다; 여기서는 일단 간단히 알아보자.
(https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB)
version, indexDB open
어렵게 정리했는데 몇마디로 요약하자면
"현재 indexDB의 version 보다 낮은 version을 open하려고 하면 에러가 발생한다"
"upgrade할 때 schema를 생성하고 success할 때 활용한다"
const INDEXDB_NAME='mydb'
// IDBFactory
const indexedDB =
window.indexedDB ||
window.mozIndexedDB ||
window.webkitIndexedDB ||
window.msIndexedDB ||
window.shimIndexedDB;
const request = indexedDB.open(INDEXDB_NAME, 1)
request.onupgradeneeded = e => {
console.log("upgrade called")
}
request.onsuccess = e => {
console.log("success")
}
request.onerror = e => {
alert("error")
}
위 플로우 차트에서 주의할 점은 upgrade만 트리거 되고 끝나는게 아니라 연이어 success event가 트리거 된다는 점이다.
indexDB를 삭제한후 리로드해보면 upgrade 이벤트가 발생한 후 success 이벤트가 발생하는 것을 확인할 수 있다.
생성된 결과는 다음에서 확인할 수 있다.
IDBObjectStore 만들고 Transaction을 통해 데이터 추가하기
// IDBObjectStore
const store = IDB.createObjectStore(storeName, { keyPath: key });
주의할점은 indexDB의 대부분의 API는 비동기적이라는 것이다. store가 만들어진 직후에 사용할 수 있지 않다.
그래서 upgrade 이벤트가 발생할 때 schema를 생성하고 테이블을 만드는 등의 작업을 진행한다.
여튼 이제 store를 만들었으니 tx를 생성하여 store에 넣어보자.
// readwrite IDBTransaction 생성
const tx = db.transaction("storeName", "readwrite");
tx.onerror = (e) => alert(`Error! ${e.target.error}`);
// 생성된 IDBObjectStore 불러오기
const store = tx.objectStore("storeName");
// IDBObjectStore에 추가!
store.add(yourObject);
Cursor를 통해 store에 저장된 데이터 읽기
// readonly한 IDBTransaction 생성
const tx = db.transaction("storeName", "readonly");
const store = tx.objectStore("storeName");
const request = store.openCursor();
request.onsuccess = (e) => {
const cursor = e.target.result;
if (cursor) {
// 다음 커서 진행
cursor.continue();
}
};
ref)
https://developer.mozilla.org/ko/docs/Web/API/IndexedDB_API