Django나 Spring 같은 서버 사이드 프레임워크는 세션(Session) 관리를 서버에서 처리하고 쿠키(Cookie) 를 통해 클라이언트를 식별하는 방식을 주로 사용합니다. 서버가 상태를 관리해 주니 편리하죠.

하지만 React, Vue, Angular와 같은 SPA(Single Page Application) 환경에서는 클라이언트(브라우저)가 많은 역할을 담당합니다. 서버와의 통신은 주로 API를 통해 데이터를 주고받을 뿐, 사용자의 상태나 UI 설정 등은 클라이언트에서 직접 관리하는 경우가 많습니다.

이때 데이터를 "어디에" 저장할지 결정해야 하며, 브라우저는 이를 위한 몇 가지 저장소를 제공합니다. 각 저장소의 특징과 용도를 명확히 아는 것은 효율적인 SPA 개발의 핵심입니다.

오늘은 브라우저의 주요 저장소인 쿠키(Cookie), 로컬 스토리지(Local Storage), 세션 스토리지(Session Storage) 그리고 IndexedDB에 대해 알아보겠습니다.




쿠키는 브라우저 저장소의 원조 격입니다. 원래 서버와 클라이언트 간의 상태를 유지(Stateful) 하기 위해 설계되었습니다.

  • 특징:

    • 작은 용량: 약 4KB로 용량 제한이 매우 작습니다.

    • 서버 전송: 가장 큰 특징입니다. 쿠키는 모든 HTTP 요청에 자동으로 포함되어 서버로 전송됩니다. 이는 서버가 클라이언트의 상태를 알아야 할 때 유용하지만, 불필요한 데이터 전송으로 성능을 저하시킬 수도 있습니다.

    • 만료 기한: Expires 또는 Max-Age 속성을 통해 만료 날짜와 시간을 설정할 수 있습니다. 설정하지 않으면 세션 쿠키(브라우저 종료 시 삭제)로 동작합니다.

    • 보안 옵션: HttpOnly (JavaScript 접근 방지), Secure (HTTPS에서만 전송) 등의 보안 설정을 할 수 있습니다.

  • 주요 용도:

    • 인증 (Authentication): 서버가 발행한 로그인 인증 토큰(JWT 등) 을 저장하여, 사용자가 페이지를 이동할 때마다 서버가 사용자를 식별할 수 있게 합니다. (특히 HttpOnly 옵션과 함께 사용)

    • 사용자 추적 및 광고: 사용자의 방문 기록이나 행동 패턴을 추적하는 데 사용됩니다. (예: 구글 애널리틱스)

    • '오늘 하루 보지 않기' 팝업


2. 로컬 스토리지 (Local Storage)

HTML5에서 도입된 웹 스토리지(Web Storage) API의 일부입니다. 쿠키의 단점(작은 용량, 자동 서버 전송)을 보완하기 위해 등장했습니다.

  • 특징:

    • 큰 용량: 브라우저마다 다르지만 보통 5MB ~ 10MB의 넉넉한 용량을 제공합니다.

    • 서버 미전송: 로컬 스토리지는 클라이언트에만 데이터를 저장하며, 서버로 자동 전송되지 않습니다. 서버가 알 필요 없는 데이터를 저장하기에 좋습니다.

    • 영구성: 데이터가 영구적으로 저장됩니다. 사용자가 직접 브라우저 캐시를 삭제하거나 JavaScript 코드로 localStorage.removeItem()을 호출하지 않는 한 데이터가 사라지지 않습니다.

    • 간편한 API: localStorage.setItem('key', 'value'), localStorage.getItem('key') 등 사용하기 쉬운 API를 제공합니다. (문자열만 저장 가능)

  • 주요 용도:

    • 사용자 설정 저장: 다크 모드/라이트 모드 설정, 언어 설정 등 사용자가 선택한 UI 설정을 저장할 때.

    • 비민감성 데이터 저장: 사용자가 마지막으로 본 콘텐츠 목록, 자동 저장 기능 등.

    • 데이터 캐싱: API 응답 중 자주 변경되지 않는 데이터를 캐싱하여 불필요한 요청을 줄일 때.


3. 세션 스토리지 (Session Storage)



로컬 스토리지와 거의 모든 특징을 공유하지만, 데이터의 생명 주기(Life Cycle) 에서 결정적인 차이가 있습니다.

  • 특징:

    • 큰 용량: 로컬 스토리지와 마찬가지로 약 5MB의 용량을 제공합니다.

    • 서버 미전송: 클라이언트에만 저장됩니다.

    • 세션 기반 생명 주기: 데이터가 현재 브라우저 탭(또는 창)에 한정됩니다. 해당 탭을 닫으면 세션 스토리지의 모든 데이터는 즉시 삭제됩니다.

    • 데이터 격리: 같은 도메인이라도 다른 탭 간에 데이터가 공유되지 않습니다.

  • 주요 용도:

    • 일회성 데이터 저장: 현재 탭에서만 유효해야 하는 정보를 저장할 때.

    • 임시 폼 데이터: 여러 단계로 이루어진 회원가입 폼이나 설문조사 작성 시, 사용자가 탭을 닫기 전까지 입력한 내용을 임시 저장하는 용도.

    • 새로고침 시 데이터 유지: 페이지를 새로고침해도 데이터는 유지되어야 하지만, 탭을 닫으면 사라져야 할 때.


4. IndexedDB

로컬/세션 스토리지가 단순한 Key-Value 저장소라면, IndexedDB는 브라우저 내에 존재하는 본격적인 트랜잭션 데이터베이스 시스템입니다.

  • 특징:

    • 대용량 저장: 수백 MB에서 수 GB까지, 사용자의 디스크 공간이 허용하는 한(브라우저 정책에 따라 다름) 매우 큰 데이터를 저장할 수 있습니다.

    • 다양한 데이터 타입: 문자열뿐만 아니라 JavaScript 객체, 파일(Blob), 배열 등 복잡한 구조의 데이터를 저장할 수 있습니다.

    • 트랜잭션(Transaction) 지원: 데이터의 무결성과 일관성을 보장합니다. 여러 작업을 하나의 단위로 묶어 처리할 수 있습니다.

    • 비동기(Asynchronous) API: IndexedDB의 모든 작업은 비동기로 처리됩니다. 이는 대용량 데이터를 읽고 쓰는 동안에도 메인 UI 스레드를 차단(Blocking)하지 않아 앱의 반응성을 유지시킵니다.

    • 인덱스(Index) 지원: 인덱스를 생성하여 특정 필드로 데이터를 매우 빠르게 검색할 수 있습니다.

  • 단점:

    • 복잡한 API: localStorage에 비해 API가 훨씬 복잡하고 사용하기 어렵습니다. (이 때문에 Dexie.js, idb 같은 래퍼(Wrapper) 라이브러리를 함께 사용하는 경우가 많습니다.)
  • 주요 용도:

    • 오프라인 웹 애플리케이션 (PWA): 네트워크 연결 없이도 작동해야 하는 앱에서 핵심 데이터를 저장합니다. (예: 오프라인 문서 편집기)

    • 대규모 애플리케이션 상태 캐싱: Gemini나 ChatGPT가 이전 대화 기록을 브라우저에 저장하거나, 복잡한 사용자 데이터를 관리할 때 사용됩니다.

    • 사용자 생성 콘텐츠 임시 저장: 사용자가 작성한 긴 글, 이미지 편집 데이터 등을 서버에 업로드하기 전 안전하게 보관합니다.


5. 한눈에 비교하기

A conceptual diagram illustrating different types of web browser storage: Cookie, Local Storage, Session Storage, and IndexedDB, each with symbolic icons representing their characteristics within a stylized browser window.

네 가지 저장소의 특징을 표로 요약하면 다음과 같습니다.

기준 쿠키 (Cookie) 로컬 스토리지 세션 스토리지 IndexedDB
용량 ~ 4KB ~ 5-10MB ~ 5MB ~ GB+ (대용량)
만료 기한 수동 설정 영구적 탭 종료 시 영구적
서버 전송 O (자동 전송) X (클라이언트 전용) X (클라이언트 전용) X (클라이언트 전용)
접근 범위 동일 도메인 동일 출처 현재 탭 동일 출처
데이터 형태 문자열 문자열 문자열 객체, 파일, Blob 등
API 동기 (복잡) 동기 (간편) 동기 (간편) 비동기 (복잡)
검색 기능 X X X O (인덱스 사용)

6. 결론: 무엇을 언제 사용해야 할까?

React와 같은 SPA를 개발할 때, 이 네 가지 저장소의 용도를 명확히 구분하면 좋습니다.

  • 쿠키 (Cookie):

    • 서버가 반드시 알아야 하는 데이터에 사용합니다. (예: 보안이 중요한 인증 토큰)

    • HttpOnly 옵션을 사용해 XSS 공격으로부터 토큰을 보호하는 것이 좋습니다.

  • 로컬 스토리지 (Local Storage):

    • 사용자가 브라우저를 껐다 켜도 유지되어야 하는 간단한 데이터에 사용합니다.

    • (예: 사용자 UI 테마 설정, 언어 선택)

  • 세션 스토리지 (Session Storage):

    • 현재 작업(탭) 중에만 필요한 임시 데이터에 사용합니다.

    • (예: 여러 단계의 폼 작성 중 임시 저장)

  • IndexedDB:

    • 구조화된 대용량 데이터오프라인 지원이 필요할 때 사용합니다.

    • (예: 복잡한 앱 상태, 대화 기록 캐싱, 오프라인 문서 데이터)

중요한 보안 참고: 로컬 스토리지, 세션 스토리지, IndexedDB는 JavaScript로 쉽게 접근할 수 있습니다. 즉, XSS(Cross-Site Scripting) 공격에 취약합니다. 비밀번호, 개인 식별 정보, 민감한 인증 토큰 등은 이곳에 절대 저장해서는 안 됩니다. (인증 토큰은 HttpOnly 쿠키를 사용하는 것이 가장 안전합니다.)