웹 스토리지는 브라우저에 데이터를 저장하는 클라이언트 사이드 메커니즘이다. localStorage, sessionStorage, Cookie, IndexedDB, Cache API 등 각각 다른 특성과 용도를 가진다.
스토리지 비교
| 항목 | Cookie | localStorage | sessionStorage | IndexedDB |
|---|
| 용량 | ~4KB | 510MB | 510MB | ~수GB |
| 서버 전송 | 자동 (매 요청) | 없음 | 없음 | 없음 |
| 만료 | 설정 가능 | 영구 | 탭 닫으면 삭제 | 영구 |
| 접근 | JS + 서버 | JS만 | JS만 | JS만 |
| 구조 | 문자열 KV | 문자열 KV | 문자열 KV | 객체 저장소 |
| 비동기 | 동기 | 동기 | 동기 | 비동기 |
localStorage 사용
javascript
// 기본 사용
localStorage.setItem('theme', 'dark');
const theme = localStorage.getItem('theme');
localStorage.removeItem('theme');
localStorage.clear();
// 객체 저장 (직렬화 필수)
const user = { id: 1, name: '홍길동', prefs: { lang: 'ko' } };
localStorage.setItem('user', JSON.stringify(user));
const saved = JSON.parse(localStorage.getItem('user') ?? 'null');
// 스토리지 이벤트 (다른 탭에서 변경 감지)
window.addEventListener('storage', (e) => {
console.log('변경된 키:', e.key);
console.log('새 값:', e.newValue);
console.log('출처:', e.url);
});
// 안전한 래퍼 (파싱 실패 대비)
function safeGet<T>(key: string, fallback: T): T {
try {
const item = localStorage.getItem(key);
return item ? JSON.parse(item) : fallback;
} catch {
return fallback;
}
}
IndexedDB (대용량 구조적 데이터)
javascript
// idb 라이브러리 사용 (권장)
import { openDB } from 'idb';
const db = await openDB('my-app', 1, {
upgrade(db) {
const store = db.createObjectStore('posts', { keyPath: 'id', autoIncrement: true });
store.createIndex('by-date', 'created');
store.createIndex('by-author', 'authorId');
}
});
// CRUD
await db.add('posts', { title: '제목', authorId: 1, created: Date.now() });
const post = await db.get('posts', 1);
const recent = await db.getAllFromIndex('posts', 'by-date',
IDBKeyRange.lowerBound(Date.now() - 7 * 86400 * 1000));
await db.delete('posts', 1);
// 트랜잭션
const tx = db.transaction(['posts', 'authors'], 'readwrite');
await tx.objectStore('posts').put({ id: 1, title: '수정됨' });
await tx.done;
관련 문서