キャッシュ制御の深淵:HTTP/1.1 `Cache-Control` を完全攻略する
ネットワークエンジニアとして現場を歩いていると、「キャッシュが消えない」「意図しない古いデータが表示される」というトラブルに必ず一度は遭遇する。これらは単なる設定ミスではなく、RFC 7234(旧 2616)が定義する「Webのキャッシュ戦略」を正しく理解していないことに起因するケースがほとんどだ。
今回は、Web API設計やインフラ運用において「必須中の必須」である`Cache-Control`ヘッダーについて、現場の視点から解き明かしていこう。
—
1. なぜ「キャッシュ」がWebの成否を分けるのか
HTTP/1.1において、ブラウザや中間キャッシュ(CDNやプロキシ)は、オリジンサーバーへ無駄なリクエストを送らないことで帯域を節約し、レイテンシを劇的に改善する。しかし、この「賢い振る舞い」こそが、デプロイ時の古いコンテンツの残留や、APIのデータ不整合という悪夢を生む。
まずは、最も重要な4つのディレクティブを整理しよう。
最強の制御コマンドたち
- `max-age=
` :
キャッシュの「寿命」を秒単位で指定する。最も一般的だ。これがある限り、ブラウザはサーバーに問い合わせることなく、手元のキャッシュを再利用する。
- `no-cache`:
「キャッシュするな」ではない。「キャッシュする前に、必ずサーバーへ検証(Revalidation)の問い合わせをせよ」という意味だ。Etag等が一致すれば、サーバーは `304 Not Modified` を返し、通信量を大幅に削減できる。
- `no-store`:
最強の拒絶。「メモリにもディスクにも一切保存するな」。個人情報や機密性の高いAPI応答にはこれが必須だ。
- `must-revalidate`:
キャッシュが期限切れ(max-age超過)になった場合、「必ず」サーバーに再検証を求める。ネットが切断されている場合、古いデータを返すことは許されず、エラー(504 Gateway Timeout)を返すことが規定されている。
—
2. 実務で遭遇する「罠」とシーケンス
ここで、よくある「なぜかキャッシュが効かない(あるいは効きすぎる)」という状況を解消するためのシーケンスを意識してほしい。
検証フロー(Revalidation)の実際
もしあなたがAPIサーバーを運用しているなら、`no-cache` を指定した際に、クライアントが `If-None-Match` ヘッダーを付けてくることを想定しなければならない。
1. ブラウザ: `GET /api/data` を送信
2. サーバー: `ETag: “v123″` と `Cache-Control: no-cache` を返す
3. ブラウザ: キャッシュを保持しつつ、次にアクセスする際は `If-None-Match: “v123″` を添える
4. サーバー: 変わっていなければ `304 Not Modified`(ボディなし)を返す。これでパケット通信量は最小化される。
—
3. 実践:コードと設定で見る実装例
理論だけでは現場は回らない。今すぐ使える設定を見ていこう。
Nginxでの設定例(インフラ側)
静的コンテンツを配信する際、キャッシュポリシーを適切に注入するのはインフラ担当者の腕の見せ所だ。
location /static/ {
# 1ヶ月キャッシュさせる
expires 30d;
add_header Cache-Control “public, max-age=2592000, immutable”;
}
location /api/ {
# APIは常に検証を強制し、機密情報は保存させない
add_header Cache-Control “no-store, no-cache, must-revalidate, proxy-revalidate”;
}
Fetch APIでの制御(フロントエンド側)
ブラウザ側で意図的にキャッシュをバイパスしたい場合、`cache` オプションを使いこなす必要がある。
// サーバーのキャッシュを無視して最新を取得したい場合
fetch(‘/api/user/profile’, {
method: ‘GET’,
cache: ‘no-store’ // ブラウザのキャッシュを完全に無視
})
.then(response => response.json())
.then(data => console.log(data));
curlによるデバッグ(トラブルシューティング)
サーバーからのレスポンスを直接確認するのは、ネットワークエンジニアの基本技能だ。
ヘッダー情報だけを抽出して確認する
curl -I -v https://api.example.com/data
期待した Cache-Control が付与されているか即座に確認できる
—
4. シニアエンジニアからの助言:最後に
最後に一つだけ覚えておいてほしい。「キャッシュの無効化は、一度有効化するよりも遥かに難しい」ということだ。
一度CDNやブラウザのキャッシュに乗ってしまうと、サーバー側で設定を変えても、ユーザー側のブラウザにあるキャッシュを強制的に破棄させる術は限られている。だからこそ、開発の初期段階から API のレスポンスヘッダーに `Cache-Control` を慎重に設計しておく必要がある。
「迷ったら `no-cache` を入れ、機密情報には `no-store`」。
この原則を守るだけで、運用フェーズでの「古いデータが残っている」という電話に悩まされる回数は劇的に減るはずだ。
次は、`Vary` ヘッダーによるキャッシュのキー制御について深掘りしよう。これもまた、CDNを運用する上では避けて通れない沼のような領域だからね。健闘を祈る。
コメント