Skip to content

IndexedDB vs LocalStorage

클라이언트에 데이터를 저장할 때 가장 많이 고민하는 두 가지입니다. 결론부터 말하면 간단한 설정값은 LocalStorage, 대용량·구조화 데이터는 IndexedDB입니다.


한눈에 비교

항목LocalStorageIndexedDB
저장 용량5~10MB수백 MB ~ GB
데이터 타입문자열만객체, Blob, File 등
동작 방식동기 (메인 스레드 블로킹)비동기
검색·필터키로만 접근인덱스, 범위 쿼리 지원
트랜잭션없음ACID 트랜잭션 지원
사용 난이도쉬움복잡 (래퍼 라이브러리 권장)

LocalStorage

키-값 쌍으로 문자열을 저장합니다. 사용법이 단순하고 동기적으로 동작합니다.

js
// 저장
localStorage.setItem("theme", "dark");

// 읽기
const theme = localStorage.getItem("theme");

// 삭제
localStorage.removeItem("theme");

객체를 저장할 때는 직렬화가 필요합니다.

js
// 저장
localStorage.setItem("user", JSON.stringify({ name: "John", age: 30 }));

// 읽기
const user = JSON.parse(localStorage.getItem("user"));

자주 쓴다면 유틸리티 함수로 감싸두는 게 편합니다.

js
const storage = {
  set(key, value) {
    localStorage.setItem(key, JSON.stringify(value));
  },
  get(key) {
    const item = localStorage.getItem(key);
    return item ? JSON.parse(item) : null;
  },
};

IndexedDB

브라우저에 내장된 NoSQL 데이터베이스입니다. 비동기로 동작하며 인덱싱과 트랜잭션을 지원합니다.

js
const request = indexedDB.open("MyDatabase", 1);

request.onupgradeneeded = (event) => {
  const db = event.target.result;
  const store = db.createObjectStore("users", { keyPath: "id" });
  store.createIndex("name", "name", { unique: false });
};

request.onsuccess = (event) => {
  const db = event.target.result;
  const tx = db.transaction(["users"], "readwrite");
  tx.objectStore("users").add({ id: 1, name: "John", age: 30 });
};

날 API가 복잡하기 때문에 실무에서는 래퍼 라이브러리를 씁니다.

래퍼 라이브러리

  • Dexie.js — 가장 인기 있고 기능이 풍부함
  • idb — Google이 만든 경량 Promise 기반 래퍼
  • localForage — LocalStorage와 유사한 API로 IndexedDB 사용
js
// Dexie.js 예시
import Dexie from "dexie";

const db = new Dexie("MyDatabase");
db.version(1).stores({ users: "++id, name, age" });

await db.users.add({ name: "John", age: 30 });
const result = await db.users.where("age").above(25).toArray();

언제 무엇을 쓸까

LocalStorage

  • 다크모드, 언어 설정 같은 사용자 환경설정
  • 5MB 미만의 단순 키-값 데이터
  • 빠르게 구현해야 할 때

IndexedDB

  • 오프라인 지원이 필요한 PWA
  • 이미지, 파일 등 Blob 데이터 저장
  • 검색·필터가 필요한 대용량 데이터
  • 오프라인 이메일, 미디어 라이브러리, 게임 세이브 데이터

두 가지를 함께 쓰는 경우도 많습니다. 사용자 설정은 LocalStorage에, 애플리케이션 데이터는 IndexedDB에 분리하는 방식입니다.


보안 주의사항

두 스토리지 모두 같은 도메인의 JavaScript에서 접근 가능합니다.

  • XSS 공격에 노출될 수 있으므로 민감한 정보(토큰, 비밀번호)는 저장하지 마세요
  • 꼭 저장해야 한다면 암호화 후 저장하세요
  • HTTPS 환경에서 사용하세요

MIT 라이선스에 따라 릴리즈되었습니다.