サイトの読み込みが遅かった経験はありませんか?
こんにちは。NTTドコモ情報システム部でWebサイトの開発運営をしている小寺智仁です。 スマホでWebサイトを開いたとき、画像の読み込みが遅くてイライラした経験はありませんか? 本記事では、AWSのCloudFrontとLambda@Edgeを活用し、画像最適化によるWeb体験の向上と運用負担軽減の方法を解説します。 この取り組みによって、
- ユーザ体験の向上
- コンテンツ管理者の運用負担軽減
- サイトのSEOの強化
の3つのメリットを同時に実現いたします。
なぜ画像最適化が必要なのか
モバイルファーストの時代、Webサイトのパフォーマンスはユーザ体験とSEOに直結します。 特にスマートフォンからのアクセスが主流となった現在、画像の軽量化やレスポンシブ対応は必須です。ただ、ユーザの置かれている状況に応じて、コンテンツ管理者が画像を用意する方法には時間とコストが必要になり、限界があります。
上記解決手段の一つとして、本稿ではAWSサービスであるCloudFrontとLambda@Edgeを用いて、画像変換をエッジサーバ上で実装するアプローチを紹介します。 イベントの選択、キャッシュキーの設計、アーキテクチャ設計に焦点を当て、レイテンシを抑える設計のポイントを紹介します。

画像最適化を実現するために採用した手法の理由と注意点
従来の手法では、コンテンツを提供しているオリジンサーバで画像を加工する方法が一般的でした。 しかし、この方法ではオリジンサーバ負荷が増大しレイテンシが悪化します。 その代替として、エッジサーバと呼ばれるユーザに物理的に近いロケーションで実行されるサーバで加工してコンテンツを提供する方法が注目されています。 エッジサーバ上を提供するためには、CDN機能で実装することが出来ます。 CDN機能を実現するサービスは複数ありますが、既存環境がAWSだったことから、CloudFrontとLambda@Edgeを採用しました。ただ、Lambda@Edgeでの設計はパッケージサイズやランタイム制約があり、他クラウドへの移行時には再設計が必要となります。

Lambda@Edgeを利用した画像加工機能の実現方法
CloudFrontとLambda@Edgeで実行できる概要
Lambda@Edgeは、AWS CloudFrontのエッジロケーションでサーバーレス関数を実行できるサービスです。 ユーザからのリクエストをCloudFrontが受け取った際、Lambda@Edgeが画像のリサイズやフォーマット変換などの処理をエッジサーバで実行します。エッジサーバで処理しているため、オリジンサーバに対して負荷をかけずに画像加工が可能となっております。 オリジンサーバからCloudFront側に送信するイベント(Origin Response)にて、画像加工を行うことでユーザ毎に最適な画像を配信できます。
- ユーザがCloudFrontに対して画像リクエストを行う
- CloudFront内にキャッシュ有無を確認する。キャッシュがある場合は、5の処理を行う
- CloudFrontがオリジンサーバに対して画像リクエストを行う
- オリジンサーバがCloudFrontに対して画像レスポンスを行う。キャッシュキーに応じてCloudFrontに紐づくLambda@Edgeで画像加工を行う。
- CloudFrontがユーザに対して画像レスポンスを行う

キャッシュキー設計について
最適な画像加工するためには、ユーザの環境に応じたキャッシュキーの設計が必要となっております。 キャッシュキーとはCDNのキャッシュを判定する要素となっております。 キャッシュの実装には、「ユーザの環境を判定する要素」と「判定した情報に基づいて画像を加工する要素」があります。 「ユーザの環境を判定する要素」は、 htmlに記載されたUser-Agentにて取得することで実現しました。User-Agentでは、Webブラウザやアプリなどがサーバにアクセスする際に、自分が「どんなソフトウェアや端末なのか」を伝えるための情報を取得することができます。 ユーザの画面サイズや拡張子が対応しているのかの情報を取得することで条件分岐を実現しました。
<picture> <source media="(max-width: 640px)" type="image/webp" srcset="画像.png?img_resize=450&img_ext=webp"> <!-- スマフォかつwebpが対応しているサイトで閲覧しているユーザ --> <source media="(max-width: 640px)" type="image/png" srcset="画像.png?img_resize=450"> <!-- スマフォかつwebpが対応していないサイトで閲覧しているユーザ --> <source type="image/webp" srcset="画像.png?img_ext=webp"> <!-- PCかつwebpが対応しているサイトで閲覧しているユーザ --> <img src="画像.png" class="" width="640" height="354"> <!-- PCかつwebpが対応していないサイトで閲覧しているユーザ --> </picture>
次に、「判定した情報に基づいて画像を加工する要素」では、クエリパラメータとして画像サイズと変換したい拡張子の情報を取得しています。
Lambda@Edgeの処理の中でクエリパラメータを分解し、各値に応じた加工をしております。上記のような要素を組み合わせることで、キャッシュ制御を実現しユーザ毎に最適な画像を提供することを実現しております。

まとめ
本稿では、CloudFrontとLambda@Edgeを利用したユーザ体験とSEOの向上させる取り組みをご紹介しました。 画像最適化への理解や他コンテンツ管理者様の設計の参考になれば幸いです。 今後もお客さまの体験価値を高めるために継続的な改善に努めてまいります。