画像 CDN の設定と最適化 - CloudFront, Cloudflare で実現する高速配信
画像 CDN とは - 従来の CDN との違いと導入メリット
画像 CDN (Content Delivery Network) は、通常の CDN のキャッシュ・配信機能に加えて、画像の動的変換 (リサイズ、フォーマット変換、品質調整) をエッジサーバーで実行する専門的なサービスです。従来の CDN が「静的ファイルをそのまま高速配信する」のに対し、画像 CDN は「リクエストに応じて最適化した画像を生成・配信する」点が根本的に異なります。
画像 CDN の主なメリット:
- 自動フォーマット変換: ブラウザの
Acceptヘッダーを解析し、WebP や AVIF に対応したブラウザには自動的に最適フォーマットで配信します。HTML の変更なしに、全ユーザーに最適なフォーマットを届けられます - 動的リサイズ: URL パラメータやクライアントヒントで指定したサイズに、エッジサーバーでリアルタイムにリサイズします。元画像を 1 つアップロードするだけで、あらゆるデバイスに最適なサイズを配信できます
- 品質の自動調整: ネットワーク速度やデバイスの能力に応じて、画像の圧縮品質を動的に調整します。低速回線では品質を下げてファイルサイズを削減し、高速回線では高品質を維持します
- グローバル配信: 世界中のエッジロケーションから配信するため、ユーザーの地理的位置に関わらず低レイテンシでの画像配信が可能です
画像 CDN を導入することで、開発者は複数サイズ・複数フォーマットの画像を事前に生成する必要がなくなり、運用コストが大幅に削減されます。元画像を 1 つ管理するだけで、全デバイス・全ブラウザに最適な画像が自動配信される理想的なワークフローが実現します。
CloudFront + Lambda@Edge による画像最適化 - AWS での構築方法
AWS CloudFront と Lambda@Edge を組み合わせることで、独自の画像最適化パイプラインを構築できます。リクエスト時に画像のリサイズ、フォーマット変換、品質調整をエッジで実行し、結果をキャッシュして以降のリクエストに高速に応答します。
アーキテクチャの概要:
- オリジン: S3 バケットに元画像を保存します。高解像度の元画像を 1 つだけアップロードすれば十分です
- Lambda@Edge (Origin Response): オリジンからの応答をインターセプトし、リクエストパラメータに基づいて画像を変換します。Sharp ライブラリを使用してリサイズ、フォーマット変換、品質調整を実行します
- CloudFront キャッシュ: 変換済み画像をエッジにキャッシュし、同じパラメータのリクエストには Lambda を実行せずにキャッシュから応答します
URL 設計例: https://cdn.example.com/images/photo.jpg?w=800&h=600&f=webp&q=80
パラメータの意味: w (幅)、h (高さ)、f (フォーマット: webp/avif/jpeg/png)、q (品質: 1-100)
Lambda@Edge の実装では、Sharp ライブラリのレイヤーを事前にビルドして Lambda Layer として登録します。Sharp はネイティブバイナリを含むため、Amazon Linux 2 環境でビルドする必要があります。Docker を使って amazonlinux:2 イメージ内でビルドするのが確実です。メモリは 512MB-1024MB を割り当て、タイムアウトは 5-10 秒に設定します。
Cloudflare Images と Polish - マネージドサービスによる簡易導入
Cloudflare は画像最適化のためのマネージドサービスを複数提供しており、Lambda@Edge のような独自実装なしに画像 CDN を導入できます。設定の手軽さと低コストが魅力です。
Cloudflare の画像最適化機能:
- Cloudflare Polish: Pro プラン以上で利用可能な自動画像最適化機能です。オリジンから配信される画像を自動的に圧縮し、WebP 対応ブラウザには WebP に変換して配信します。設定はダッシュボードのトグルを ON にするだけで、コードの変更は一切不要です
- Cloudflare Images: 画像のアップロード、保存、変換、配信を一括で提供するフルマネージドサービスです。バリアント (サイズ・品質の組み合わせ) を事前に定義し、URL で指定して配信します。月額 $5 から利用可能で、小規模サイトに最適です
- Image Resizing: Business プラン以上で利用可能な動的リサイズ機能です。URL パラメータで任意のサイズ・品質・フォーマットを指定でき、Lambda@Edge と同等の柔軟性を持ちます
Cloudflare Polish の設定手順:
- Cloudflare ダッシュボードで Speed → Optimization → Image Optimization に移動
- Polish を「Lossless」または「Lossy」に設定 (Lossy 推奨: より高い圧縮率)
- WebP 変換を有効化
- AVIF 変換を有効化 (対応ブラウザに自動配信)
Polish は既存サイトへの導入が最も簡単な方法です。DNS を Cloudflare に向けるだけで、全画像が自動的に最適化されます。ただし、動的リサイズやアスペクト比の変更はできないため、レスポンシブ画像の完全な最適化には Image Resizing が必要です。
キャッシュ戦略の設計 - ヒット率を最大化する設定
画像 CDN のパフォーマンスはキャッシュヒット率に大きく依存します。キャッシュヒット率が高いほど、エッジサーバーからの高速応答が増え、オリジンへのリクエストと画像変換の実行回数が減少します。目標はキャッシュヒット率 95% 以上です。
キャッシュヒット率を高める設計:
- URL の正規化: 同じ画像に対して異なる URL パターンが生成されないよう、パラメータの順序を固定します。
?w=800&h=600&f=webpと?f=webp&w=800&h=600が別のキャッシュエントリになることを防ぎます。Lambda@Edge の Viewer Request イベントでパラメータをソートする処理を入れます - サイズのバケット化: 任意のサイズを許可するとキャッシュが分散します。許可するサイズを事前に定義し (例: 320, 640, 960, 1280, 1,920 px)、リクエストされたサイズを最も近い定義済みサイズに丸めます
- Cache-Control ヘッダー: 画像は頻繁に変更されないため、長い TTL を設定します。
Cache-Control: public, max-age=31536000, immutable(1 年) が推奨です。画像を更新する場合はファイル名を変更 (コンテンツハッシュを含める) してキャッシュを無効化します - Vary ヘッダーの最小化:
Vary: Acceptを設定すると、ブラウザの Accept ヘッダーの違いでキャッシュが分割されます。フォーマット変換を URL パラメータで制御する場合は Vary ヘッダーを使わず、URL ベースでキャッシュを分離します
CloudFront のキャッシュポリシー設定では、クエリ文字列をキャッシュキーに含める設定が必要です。「すべてのクエリ文字列を含める」ではなく、画像変換に使用するパラメータ (w, h, f, q) のみをホワイトリストで指定し、不要なパラメータ (トラッキング用の utm_ など) がキャッシュを分割しないようにします。
Client Hints による自動最適化 - ブラウザとの連携
Client Hints は、ブラウザがサーバーにデバイス情報 (画面幅、DPR、ネットワーク速度) を HTTP ヘッダーで送信する仕組みです。画像 CDN がこの情報を活用することで、URL パラメータなしに最適な画像を自動配信できます。
画像最適化に関連する Client Hints ヘッダー:
- DPR: デバイスピクセル比。
DPR: 2なら 2x 画像を配信 - Viewport-Width: ビューポートの幅 (CSS ピクセル)。レスポンシブ画像のサイズ決定に使用
- Width: 画像の表示幅 (CSS ピクセル)。
sizes属性から計算された値 - Save-Data: データセーバーモードが有効かどうか。有効なら低品質・小サイズの画像を配信
- ECT (Effective Connection Type): ネットワーク速度の推定値 (4g, 3g, 2g, slow-2g)。低速回線では品質を下げる
Client Hints を有効にするには、サーバーから Accept-CH レスポンスヘッダーを送信する必要があります:
Accept-CH: DPR, Viewport-Width, Width
または HTML の <meta> タグで指定します:
<meta http-equiv="Accept-CH" content="DPR, Viewport-Width, Width">
CloudFront では、Client Hints ヘッダーをオリジンに転送するようキャッシュポリシーを設定し、Lambda@Edge でヘッダー値に基づいて画像を変換します。ただし、Client Hints をキャッシュキーに含めるとキャッシュが細分化されるため、DPR は 1x/2x/3x の 3 段階に丸め、Viewport-Width はバケット化して使用します。
注意点として、Client Hints はクロスオリジンリクエストではデフォルトで送信されません。画像 CDN が別ドメインの場合、Permissions-Policy ヘッダーで明示的に許可する必要があります。
モニタリングとコスト最適化 - 運用時の監視ポイント
画像 CDN を運用する際は、パフォーマンス指標とコストの両面を継続的に監視し、最適な状態を維持することが重要です。設定ミスや想定外のトラフィックパターンにより、コストが急増したりパフォーマンスが低下したりするリスクがあります。
監視すべき主要指標:
- キャッシュヒット率: CloudFront のメトリクスで確認。95% 以上を目標とし、低下した場合はキャッシュキーの設計を見直します。CloudFront の「Cache Statistics」レポートで日次のヒット率推移を確認できます
- オリジンリクエスト数: キャッシュミスによるオリジンへのリクエスト数。急増した場合はキャッシュの無効化 (Invalidation) が過剰に実行されていないか確認します
- Lambda@Edge の実行時間: 画像変換の処理時間。P99 レイテンシが 5 秒を超える場合は、メモリ割り当ての増加や画像サイズの上限設定を検討します
- エラー率: 4xx/5xx レスポンスの割合。不正なパラメータによる変換エラーや、メモリ不足による Lambda のタイムアウトを検出します
- 帯域幅コスト: CloudFront のデータ転送量。画像の圧縮率が適切か、不必要に大きな画像が配信されていないか確認します
コスト最適化のテクニック:
- Lambda@Edge の実行回数を減らすため、キャッシュ TTL を最大限長く設定する
- 画像の最大サイズに上限を設ける (例: 幅 2,560 px 以上のリクエストは拒否)
- 不正なパラメータや攻撃的なリクエスト (大量の異なるサイズを要求) を WAF でブロックする
- S3 のストレージクラスを Intelligent-Tiering に設定し、アクセス頻度に応じて自動的にコストを最適化する