🤔
indexedDB
는 무엇이며, 어떻게 사용하는 걸까? 이번 시간에는indexedDB
정의와 사용법에 대해 알아보았다! (마지막에는 vue에서는 indexedDB를 어떻게 사용하는지 링크도 공유해두었다 참고해보자!)
1. indexedDB?
1) indexedDB는 무엇일까?
(1) indexedDB의 정의
- 우리가 데이터를 저장할 때, 클라이언트 스토리지(브라우저 제공 db)를 이용할 수 있다.
- 클라이언트 스토리지에는
localStorage
,cookies
,indexedDB
가 존재한다.
❓ 그런데 localStorage 대신 indexedDB를 쓰는 이유가 있을까?
- localStoage의 경우
: 적은 양의 데이터를 저장할 때 유용하다.
: 동기적으로 작동하며, 오직 문자열 타입의 키&값만을 사용할 수 있다.
: 그렇기 때문에JSON.stringify
,JSON.parse
와 같은 함수가 꼭 필요하다. - indexedDB의 경우
: 그에 반해 indexedDB는 많은 양의 구조화된 데이터를 저장할 때 유용하다.
: localStoage와 달리, JS가 인식할 수 있는 자료형과 객체를 저장할 수 있다.
: 키, 값 형태로 데이터가 저장되며 문자열 타입이 아니어도 된다.
: 특이한 점은 비동기적으로 작동한다는 점이다.
(2) indexedDB 패턴
❓ indexedDB는 localStoage보다 절차가 조금 복잡한데, 기본 패턴은 아래와 같다.
- 데이터베이스 열기
- 데이터베이스에 객체 저장소(Object store) 생성하기
- 트랜젝션(Transaction) 시작하기 (데이터 읽기, 쓰기 제거 등 데이터베이스 작업 요청)
- 이벤트 리스너를 사용하여 요청이 완료될때까지 기다리기
- 요청 결과를 가지고 어떤 동작하기
2. indexedDB 사용해보기
1) 데이터베이스 열기
(1) open 함수로 dataBase 열기
- 브라우저에서 여러 개의 데이터베이스를 만들 수 있다.
- 데이터베이스는 버전 정보를 가지고 있으며, 여러 개의 ObjectStore(객체 저장소)를 가질 수 있다.
- 단, 데이터베이스 수정시 버전을 수정해줘야 한다!
open
명령어를 사용해 데이터베이스를 열도록 요청할 수 있다.
window.indexedDB.open(db_name, version)
(2) 예시 코드
- 아래 코드는 데이터베이스를 여는 과정이다.
// 1. indexedDB 객체 가져오기
const idxedDB = window.indexedDB;
// 2. 브라우저에서 지원하는지 체크하기
if (!idxedDB) window.alert('해당 브라우저에서는 indexedDB를 지원하지 않습니다.')
else {
let db;
const request = idxedDB.open('SampleDB'); // 3. SampleDB(db) 열기
request.onerror =(e)=> alert('failed');
request.onsuccess =(e)=> db = request.result;
}
2) database에 ObjectStore 추가하기
(1) ObjectStore 생성하기
- ObjectStore는 데이터를 담는 공간이다.
- 여러 개의 레코드(key-value)를 가진다.
- ObjectStore의 이름은 고유해야 한다.
- 각 객체에 유일성을 부여하기 위해
keyPath
를 정의해야 한다. createObjectStore
를 사용해 특정 DB에 ObjectStore를 추가할 수 있다.- 단,
createObjectStore
는 onupgradeneeded 이벤트와 함께 써야 한다.
IDBRequest.createObjectStore('store_name', {keyPath: 'id'})
(2) onupgradeneeded?
onupgradeneeded
는 아래와 같은 상황에 발생하는 이벤트이다.
이벤트 발생 상황 |
---|
새로운 데이터 베이스 만들 때 |
기존 데이터베이스의 버전을 높일 때(db를 열었는데(open), 이전보다 높은 버전을 지정하는 경우) |
- 해당 이벤트가 성공하며
onsuccess
핸들러가 트리거 된다. - 단
indexedDB.open(name, version).onupgradeneeded
와 같은 형식은 지원하지 않는다.
(3) 예시 코드
- 아래 코드는
SampleDB
를 열고, 해당db
에name
이라는 이름의 ObjectStore를 추가한 모습이다.
// 1. indexedDB 객체 가져오기
const idxedDB = window.indexedDB;
// 2. 브라우저에서 지원하는지 체크하기
if (!idxedDB) window.alert('해당 브라우저에서는 indexedDB를 지원하지 않습니다.')
else {
let db;
const request = idxedDB.open('SampleDB'); // 3. SampleDB(db) 열기
request.onupgradeneeded =(e)=> {
db = e.target.result;
db.createObjectStore('name', {keyPath: 'id'}); // 4. name저장소 만들고, key는 id로 지정
request.onerror =(e)=> alert('failed');
request.onsuccess =(e)=> db = request.result; // 5. 성공시 db에 result를 저장
}
}
3) 트랜잭션 시작하기
indexedDB.open
성공시(onsuccess),transaction
을 사용해, 저장소에 데이터를 입력할 수 있다.- 단, 새 데이터베이스에서 작업을 하기전에 트랜잭션을 시작해야 한다!
(1) 트랜잭션은 무엇일까?
❓ 트랜잭션이 뭐길래, 이걸 먼저 시작해야할까?
- 트랜잭션은 db의 상태르 변화시키기 위해 수행하는 작업 단위를 말한다.
- 트랜잭션은 데이터베이스 객체 단위로 작동하며, 그렇기 때문에 사용할 객체 저장소를 지정해줘야 한다.
- 우리는 트랜잭션을 통해, 객체 저장소에 접근하거나 데이터 요청을 할 수 있다.
- 트랜잭션은 다음 3가지 모드가 있다.(
readonly
,readwrite
,versionchange
)
(2) 트랜잭션 3가지 모드
versionchange 모드
- 아래와 같은 상황은 versionchange에서 처리해줘야한다.
상황 |
---|
객체 저장소를 만들 때 |
객체 저장소에서 인덱스를 만들거나 삭제할 때 |
데이터베이스의 스키마나 구조를 변경할 때 |
- 해당 트랙잭션은
indexedDB.open
시 버전을 지정한 경우에 시작해야 한다. - 단, 일부 webKit 브라우저의
open()
는 데이터베이스의 이름(name
) 하나만 인자로 받는다. - 따라서 별도로
setVersion()
를 호출해야 한다.
readonly 모드
- 객체 저장소의 레코드를 읽을 때, readonly에서 처리해줘야한다.
IDBDatabase.transaction
으로 해당 모드를 열 수 있다.
readwrite 모드
- 아래와 같은 상황은 readwrite에서 처리해줘야한다.
상황 |
---|
객체 저장소의 레코드를 읽을 때 |
존재하는 객체 저장소에 변경점을 기록할 때 |
데이터베이스의 스키마나 구조를 변경할 때 |
IDBDatabase.transaction
으로 해당 모드를 열 수 있다.
(3) transaction() 사용하기
- 우리는
transaction()
을 사용해 특정 객체 저장소에 접근할 수 있다. - 모드가 지정되지 않는다면 기본적으로 트랜잭션은
readonly
모드로 열린다. - 해당 메소드는 객체 저장소에 접근할 수 있는 트랜잭션 객체를 반환한다.
IDBDatabase.transaction(store_names, mode, options);
// 예시
IDBDatabase.transaction(['store1', 'store2']); // 객체저장소가 여러개에 접근할 경우
IDBDatabase.transaction('store1'); // 객체저장소가 하나에 접근할 경우
(4) 예시 코드
function writeIdxedDB(names) {
const request = window.indexedDB.open('SampleDB');
request.onerror =(e)=> {
alert('DataBase error', e.target.errorCode);
}
request.onsuccess =(e)=> {
const db = request.result;
const transaction = db.transaction(['name'], 'readwrite');
//person 객체 저장소에 읽기&쓰기 권한으로 transaction 생성
// 완료, 실패 이벤트 처리
transaction.oncomplete =(e)=> {
console.log('success');
}
transaction.onerror =(e)=> {
console.log('fail');
}
// transaction으로
const objStore = transaction.objectStore('name');
for (const name of names) {
const request = objStore.add(name); // 저장
request.onsuccess =(e)=> console.log(e.target.result);
}
}
}
const names = [{id: 1, name: 'a'}, {id: 2, name: 'b'}, {id: 3, name: 'c'}];
writeIdxedDB(names);
4) 본격적으로 CRUD 해보기
(1) db에서 데이터 조회하기
- 특정 데이터값을 조회하려면 해당 데이터의 key값을 사용하면 된다.
function getIdxedDBValue(key) {
const request = window.indexedDB.open('SampleDB'); // 1. DB 열기
request.onerror =(e)=> console.log(e.target.errorCode);
request.onsuccess =(e)=> {
const db = request.result;
const transaction = db.transaction('name');
transaction.onerror =(e)=> console.log('fail');
transaction.oncomplete =(e)=> console.log('success');
const objStore = transaction.objectStore('name');
const objStoreRequest = objStore.get(key); // 2. get으로 데이터 접근
objStoreRequest.onsuccess =(e)=> {
console.log(objStoreRequest.result)
}
}
}
getIdxedDBValue(1); // { id:1, name:"a" }
- 전체 데이터를 조회하려면,
cursor
를 사용해 데이터를 조회할 수 있다.
function getIdxedDBValues() {
const request = window.indexedDB.open('SampleDB'); // 1. DB 열기
request.onerror =(e)=> console.log(e.target.errorCode);
request.onsuccess =(e)=> {
const db = request.result;
const transaction = db.transaction('name');
transaction.onerror =(e)=> console.log('fail');
transaction.oncomplete =(e)=> console.log('success');
const objStore = transaction.objectStore('name'); // 2. name 저장소 접근
const cursorRequest = objStore.openCursor();
cursorRequest.onsuccess =(e)=> {
let cursor = e.target.result;
if (cursor) {
const value = objStore.get(cursor.key); // 3. 커서를 사용해 데이터 접근
value.onsuccess =(e)=> {
console.log(e.target.result);
}
cursor.continue(); // 4. cursor로 순회
}
}
}
}
getIdxedDBValues(); // { id:1, name:"a" }, {id: 2, name: 'b'}, {id: 3, name: 'c'}
(2) db에서 데이터 수정하기
put()
을 사용해 db의 데이터 값을 수정할 수 있다.
function updateIdxedDBValue(key, value) {
const request = window.indexedDB.open('SampleDB'); // 1. db 열기
request.onerror =(e)=> console.log(e.target.errorCode);
request.onsuccess =(e)=> {
const db = request.result;
const transaction = db.transaction('name', 'readwrite');
transaction.onerror =(e)=> console.log('fail');
transaction.oncomplete =(e)=> console.log('success');
const objStore = transaction.objectStore('name');// 2. name 저장소 접근
const objStoreRequest = objStore.get(key); // 3. key값으로 데이터 접근
objStoreRequest.onsuccess =(e)=> {
const updateRequest = objStore.put(value); // 4. 수정
updateRequest.onerror =(e)=> console.log('udpate error');
updateRequest.onsuccess =(e)=> console.log('success');
}
}
}
updateIdxedDBValue(1, {id: 1, name: 'vvvv'});
updateIdxedDBValue(2, {id: 2, name: 'bbbbb'});
- 단, put을 할 때, 키(key)를 포함한 객체를 넘겨야 한다.
- 만약 key값을 넘기지 않고 값만 바꾸고 싶다면 아래 방법을 사용하자
...
objStoreRequest.onsuccess =(e)=> {
const data = objStoreRequest.result; // 해당 키의 데이터 다 가져오기
data.name = '어쩌구저쩌구로 변경'; // 데이터에서 일부 속성값 변경
const updateRequest = objStore.put(data); // 변경된 data를 넘김
}
(3) db에서 데이터 삭제하기
delete()
를 사용해 특정 키의 값 삭제할 수 있다.
function deleteIdxedDBValue(key) {
const request = window.indexedDB.open('SampleDB'); // 1. db 열기
request.onerror =(e)=> console.log(e.target.errorCode);
request.onsuccess =(e)=> {
const db = request.result;
const transaction = db.transaction('name', 'readwrite');
transaction.onerror =(e)=> console.log('fail');
transaction.oncomplete =(e)=> console.log('success');
const objStore = transaction.objectStore('name'); // 2. name 저장소 접근
const objStoreRequest = objStore.delete(key); // 3. 삭제하기
objStoreRequest.onsuccess =(e)=> {
console.log('deleted');
}
}
}
deleteIdxedDBValue(1);
clear()
를 사용해 특정 저장소의 데이터 값을 모두 삭제할 수 있다.
function clearIdxedDBValue() {
const request = window.indexedDB.open('SampleDB'); // 1. db 열기
request.onerror =(e)=> console.log(e.target.errorCode);
request.onsuccess =(e)=> {
const db = request.result;
const transaction = db.transaction('name', 'readwrite');
transaction.onerror =(e)=> console.log('fail');
transaction.oncomplete =(e)=> console.log('success');
const objStore = transaction.objectStore('name'); // 2. name 저장소 접근
const objStoreRequest = objStore.clear(); // 3. 전체 삭제
objStoreRequest.onsuccess =(e)=> {
console.log('cleared');
}
}
}
clearIdxedDBValue();
반응형
'개발 기술 > 개발 이야기' 카테고리의 다른 글
nvm으로 node버전 관리하기(mac) (0) | 2022.02.15 |
---|---|
Mock Service Worker (feat. vue) (0) | 2022.02.03 |
JS 클린코드 <변수편> (0) | 2022.01.15 |
디자인 패턴2, 모듈 패턴이란? (0) | 2022.01.12 |
이중배열(2d array)에서 최고, 최저값 찾기 (0) | 2022.01.02 |
댓글