IndexedDB를 사용한 CRUD 구현

Singsoong·2022년 11월 21일
0

react

목록 보기
1/6
post-thumbnail
  • 프로젝트 진행 중 브라우저를 나가기 전까지 실시간 데이터들이 저장 되어야 한다는 요구사항이 있었다.
  • 실시간 데이터는 1초마다 매번 쌓이고, 용량이 적지 않았다.

(23/5/9) 지금 와서 생각하니까 전역 상태 관리 라이브러리를 사용해도 되잖아..

📌 웹 스토리지 선택하기

  • 브라우저에 저장할 수 있는 저장소가 여러가지 있다.
  • 네트워크로 불러온 리소스나 파일을 캐싱해야 한다면 캐시 스토리지 API를 활용하는게 좋고, 아니면 IndexedDB를 활용하는 것이 좋다고 한다.
  • IndexedDB 말고도 대표적으로 두 가지가 더있다.
    • 세션 스토리지 : 탭 안에서만 유효하며 탭이 닫히면 스토리지도 종료된다. 용량 제한은 5MB이며 문자열만 저장할 수 있다. 동기 방식으로 동작하여 메인 스레드 연산을 중단시킨다. 탭안에서만 유효하다.
    • 로컬 스토리지 : 동기 방식으로 동작하며, 메인 스레드 연산을 중단시킨다. 용량 제한은 마찬가지로 5MB이며 문자열만 저장할 수 있다.
  • 세션 스토리지와 로컬 스토리지 모두 용량 제한이 5MB라, 실시간 데이터를 20분 쌓게 되면 5MB가 충분히 넘기 때문에 선택지에서 제외되었다.
  • IndexedDB는 MB 단위부터 GB 단위 이상도 저장이 가능하다. 스토리지에 저장할 수 있는 양은 디바이스 스토리지 크기에 따라 달라진다.
    • Chrome 기반 브라우저는 디스크 전체 용량의 80% 까지 저장할 수 있지만, 공식 Chrome은 디스크 전체 용량의 60% 까지 저장할 수 있다.
    • Firefox는 디스크 빈 용량의 50%까지 저장할 수 있다.

📌 저장소 만들기 (Create)

export function createIndexedDB() {
  /* indexedDB를 지원하지 않는 브라우저면 경고창을 생성 */
  if (!window.indexedDB) {
    window.alert("browser doesn't support IndexedDB");
  } else {
    let db;
    /* realTimeData라는 저장소를 생성했다.*/
    let request = window.indexedDB.open("realTimeData");

    request.onupgradeneeded = function (event) {
      let db = event.target.result;
      let objectStore = db.createObjectStore("data", { keyPath: "id" });
    };

    request.onerror = function (event) {
      console.error("indexedDB not created");
    };
  }
}
  • IndexedDB는 key-value 저장소이다. 따라서 key 값을 지정해야 한다.
  • Store를 만드는 과정 중에 key 값을 지정하는데 value의 컬럼중에 id를 new Date.getTime()으로 유니크하게 생성하는데, 이 값을 key값으로 사용하기로 하였다.

📌저장소에 값 넣기 (Update)

  • 웹소켓을 통해 실시간으로 값을 1초마다 받아온다. 이 값을 만들어두었던 저장소에 넣으려 한다.
export function writeIndexedDB(data) {
  let request = window.indexedDB.open("realTimeData");

  request.onerror = (event) => {
    console.error(event.target.errorCode);
  };

  request.onsuccess = (event) => {
    let db = event.target.result;
    let tx = db.transaction(["data"], "readwrite");

    tx.onerror = (event) => {
      console.error("tx error");
    };

    let objectStore = tx.objectStore("data");
    data.map((item) => {
      objectStore.add(item);
    });
  };
}

  • 값이 잘쌓이는것을 확인할 수 있다. indexedDB는 개발자도구에서 Application 탭에 들어간 뒤 Storage > IndexedDB에서 확인할 수 있다.

📌 저장소 값 조회하기

  • 실시간 데이터들을 저장해두었다가 차트로 표현해야 한다.
  • Promise를 return하여 비동기 함수를 만들었다.
export function selectIndexDB() {
  return new Promise(function (resolve, reject) {
    let returnList = [];
    let request = window.indexedDB.open("realTimeData");
    request.onerror = (event) => {
      reject(event.target.errorCode);
    };

    request.onsuccess = (event) => {
      let db = event.target.result;
      let tx = db.transaction(["data"], "readwrite");

      tx.onerror = (event) => {
        reject("tx error");
      };

      let store = tx.objectStore("data");
      let req = store.getAll();
      req.onsuccess = function (event) {
        let temp = event.target.result;
        temp.map((item) => {
          returnList.push(item.val[0]);
        });
        resolve(returnList);
      };


    };
  });
}
  • 조회하는 함수를 사용할 때는 callback을 사용하였다.
selectIndexedDB().then((res) => {...});

📌 저장소 삭제하기 (Drop)

  • 요구사항 중, 브라우저에서 나가게 되면 실시간 데이터는 삭제되어야 한다.
  • 따라서 브라우저 나갔음을 감지하는 이벤트를 추가한다.
    (window.addEventListener("unload", () => {deleteIndexedDB()})
/* indexDB 데이터베이스를 통째로 삭제하는 func */
export function deleteIndexedDB() {
  let req = indexedDB.deleteDatabase("realTimeData");
}

📌 저장소 값 삭제하기 (Delete)

  • 실시간 값을 최대 500개까지만 가지고 있는게 요구사항이었으며, 만약 500개가 넘어서면 가장 오래된 값부터 지워나간다. (window size : 500)
/* 실시간 데이터가 500개 이상이 되면 제일 오래된 값부터 지워나가는 func */
export function deleteRecordIndexedDB() {
  let request = window.indexedDB.open("realTimeData");

  request.onerror = (event) => {
    console.error(event.target.errorCode);
  };

  request.onsuccess = (event) => {
    let db = event.target.result;
    let tx = db.transaction(["data"], "readwrite");

    tx.onerror = (event) => {
      console.error("tx error");
    };

    let store = tx.objectStore("data");
    let req = store.getAll();
    req.onsuccess = function (event) {
      let temp = event.target.result;
      if (temp.length > 501) {
        store.delete(temp[0].id);
      }
    };
  };
}
  • 저장소의 데이터를 가져온 뒤 그 길이가 500이 넘게 되면 가장 오래된 값을 지운다.
  • 윈도우 사이즈가 500인 데이터 저장소를 구현하였다.

📌 참고한 사이트

https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
https://velog.io/@xcv3549/IndexedDB%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90


profile
Web Developer

0개의 댓글