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 공격에 취약하다.
두 공격을 모두 완화하려면 HttpOnly와 SameSite 옵션을 함께 설정하는 것이 좋다.


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 연동 가능