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オプションとともに使用)

    • ユーザー追跡と広告: ユーザーの訪問履歴や行動パターンを追跡するために使用されます。(例:Googleアナリティクス)

    • 「今日一日見ない」ポップアップ


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スレッドがブロック(Block)されず、アプリの反応性が維持されます。

    • インデックス(Index)サポート: インデックスを作成して特定のフィールドでデータを非常に速く検索できます。

  • 短所:

    • 複雑なAPI: localStorageに比べてAPIがはるかに複雑で使いにくいです。(このため、Dexie.jsidbなどのラッパー(Wrapper)ライブラリと一緒に使用することが多いです。)
  • 主な用途:

    • オフラインWebアプリケーション (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を開発する際、これら4つのストレージの用途を明確に区別するのが良いです。

  • クッキー (Cookie):

    • サーバーが必ず知るべきデータに使用します。(例:セキュリティが重要な認証トークン)

    • HttpOnlyオプションを使用してXSS攻撃からトークンを保護するのが良いです。

  • ローカルストレージ (Local Storage):

    • ユーザーがブラウザを再起動しても維持されるべき簡単なデータに使用します。

    • (例:ユーザーUIテーマ設定、言語選択)

  • セッションストレージ (Session Storage):

    • 現在の作業(タブ)中にのみ必要な一時データに使用します。

    • (例:いくつかの段階のフォーム作成中に一時保存)

  • IndexedDB:

    • 構造化された大規模データオフラインサポートが必要な時に使用します。

    • (例:複雑なアプリの状態、会話履歴キャッシング、オフライン文書データ)

重要なセキュリティの参考: ローカルストレージ、セッションストレージ、IndexedDBはJavaScriptで簡単にアクセスできます。つまり、XSS(クロスサイトスクリプティング)攻撃に脆弱です。パスワード、個人識別情報、敏感な認証トークンなどはここに絶対に保存すべきではありません。(認証トークンはHttpOnlyクッキーを使用するのが最も安全です。)