Skip to content

Web Storage의 동작 원리와 보안

1. Web Storage란?

웹 스토리지는 브라우저 내부에 데이터를 저장하기 위한 API이다. 대표적으로 다음 4가지 방식이 있다.

저장소수명저장 위치크기 제한특징
localStorage브라우저를 닫아도 남음브라우저 로컬약 5~10MB문자열만 저장, 도메인 단위 격리
sessionStorage탭 종료 시 삭제브라우저 세션약 5MB세션(탭) 단위 저장
cookie수명 설정 가능서버와 자동 전송약 4KB서버 통신 시 헤더로 전송됨
IndexedDB영구 저장브라우저 DB수백MB~GB구조화된 데이터 저장 가능

2. Web Storage의 동작 원리 — same-origin policy

출처가 다르면 완전히 다른 저장소처럼 취급된다.

웹 스토리지는 도메인(origin) 단위로 격리되어 있다. 즉, https://example.com에서 저장한 데이터는 https://another.com이나 http://example.com(http/https 차이)에서는 접근할 수 없다.

plaintext
https://example.com       접근 가능
https://example.com:3000  포트가 다르면 다른 origin
http://example.com        프로토콜이 다르면 다른 origin
https://sub.example.com   서브도메인은 다른 origin

브라우저를 바꾸거나 기기를 옮기면 물리 저장소가 달라져 데이터가 존재하지 않는다.


3. localStorage의 구조와 직렬화

모든 데이터는 문자열 형태로 저장된다.
객체를 그대로 저장하면 [object Object]로 변환되므로, 반드시 JSON.stringify()를 이용해야 한다.

js
localStorage.setItem("user", JSON.stringify({ name: "Binny" }));
const user = JSON.parse(localStorage.getItem("user"));

4. localStorage의 한계 (성능/기능 측면)

localStorage는 HTML5 초창기, 빠른 접근을 목표로 만들어졌기 때문에 여러 제약이 있다.

  • 문자열만 저장 가능 → 객체는 JSON.stringify()로 변환 필요
  • 동기적 API → 대용량 데이터 처리 시 메인 스레드를 블로킹
  • 보안 취약성 → XSS(스크립트 주입 공격)에 노출 가능
  • 용량 제한 → 브라우저마다 다르지만 5~10MB 수준

즉, localStorage는 빠른 임시 저장소로는 유용하지만, 안전하거나 대용량을 다루기엔 적합하지 않다. 복잡한 데이터에는 IndexedDB가 권장된다.


구분localStoragecookie
저장 위치브라우저 로컬브라우저 + 서버
용량약 5~10MB약 4KB
만료수동 삭제 전까지만료일로 자동 삭제
접근 방식JS에서 접근 가능JS 접근 제한 가능 (HttpOnly)
전송 여부서버에 자동 전송요청 시 자동 전송
주요 용도UI 상태, 임시 데이터인증/세션 관리

쿠키는 서버와 자동으로 주고받는 데이터, localStorage는 클라이언트 전용 저장소라는 게 가장 큰 차이다.


6. 보안 이슈 — localStorage는 안전하지 않다.

localStorage는 JavaScript로 접근 가능한 공간이다.
만약 XSS 공격이 발생하면 공격자가 데이터를 그대로 읽을 수 있다.

js
// 예: 악성 스크립트 삽입
console.log(localStorage.getItem("access_token"));

그래서 로그인 토큰을 localStorage에 저장하는 건 매우 위험하다.

안전한 쿠키 설정

  • HttpOnly: JavaScript 접근 차단
  • Secure: HTTPS 연결에서만 전송
  • SameSite: 교차 사이트 요청 제한

localStorage는 XSS 공격에, 쿠키는 CSRF 공격에 취약하다.
두 공격을 모두 완화하려면 HttpOnlySameSite 옵션을 함께 설정하는 것이 좋다.


7. IndexedDB - 구조화된 데이터 저장소

오프라인 지원, 대용량 상태 저장, 캐시용으로 사용되는 브라우저 내 데이터베이스

  • 비동기 API로 작동해 메인 스레드를 블로킹하지 않음
  • 객체 단위 저장 가능 (JSON 구조 그대로)
  • 트랜잭션 기반으로 데이터 일관성 유지
  • PWA / 오프라인 캐시 / 이미지 저장 등에 자주 사용됨

IndexedDB는 SQL이 아닌 Key-Value 기반 DB이며,
Service Worker와 함께 사용하면 네트워크 끊김에도 데이터 유지가 가능하다.


8. IndexedDB의 구조와 동작

plaintext
Database (DB)
 ├─ Object Store (테이블 유사)
 │   ├─ Record (key-value 데이터)
 │   └─ Index (검색 속성)
 └─ Transaction (읽기/쓰기 단위)
  • Database: 전체 스토리지 컨테이너
  • Object Store: 데이터를 저장하는 실제 공간 (테이블 유사)
  • Record: key-value로 저장된 개별 데이터
  • Index: 특정 필드 기준으로 빠르게 검색 가능
  • Transaction: 데이터 조작 시 무결성을 보장

기본 사용 예시

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

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

request.onsuccess = (event) => {
  const db = event.target.result;
  const tx = db.transaction("users", "readwrite");
  const store = tx.objectStore("users");
  store.put({ id: 1, name: "Binny" });
};
  • 모든 작업은 트랜잭션 내부에서만 수행되며, 도중 오류 시 자동 복구된다.

9. localStorage vs IndexedDB

항목localStorageIndexedDB
API동기적비동기적
구조단일 key-valueObject Store + Index
데이터문자열만 저장객체 형태 그대로 저장
성능빠르지만 제한적대용량 데이터 처리 가능
보안XSS에 취약동일 출처 정책 동일

10. Zustand persist와 IndexedDB

Zustand의 persist 미들웨어는 기본적으로 localStorage를 사용하지만,
옵션으로 storage 옵션을 커스터마이징하여 IndexedDB 기반 저장소로 변경할 수 있다.

js
import { create } from "zustand";
import { persist, createJSONStorage } from "zustand/middleware";

const useStore = create(
  persist(
    (set) => ({
      items: [],
      addItem: (item) => set((s) => ({ items: [...s.items, item] })),
    }),
    {
      name: "items-db",
      storage: createJSONStorage(() => indexedDBStorage),
    }
  )
);

💡 indexedDBStorage는 Zustand가 기본 제공하지 않는다.

직접 IndexedDB 접근 로직을 구현하여 전달해야 한다.


11. Zustand persist의 동작 원리

js
const useResultStore = create(
  persist(
    (set) => ({
      results: [],
      addResult: (r) => set((s) => ({ results: [...s.results, r] })),
    }),
    { name: "quiz-results" } // localStorage key
  )
);
  • persist는 상태를 JSON으로 직렬화해 저장/복원하는 단순 미들웨어다.
    암호화나 보안 기능은 포함되어 있지 않으므로, 민감한 데이터 저장에는 부적합하다.

정리

선택 기준추천 저장소이유
가벼운 상태 저장 (UI, 캐시)localStorage빠르고 단순
세션 단위 데이터sessionStorage탭별로 격리
인증/보안 관련 데이터Cookie (HttpOnly)서버 통신 시 안전
오프라인/대용량 저장IndexedDB구조화된 데이터 저장 가능
전역 상태 유지 (클라이언트)Zustand persistlocalStorage/IndexedDB 연동 가능