サービス開発でよくある悩みが、ユーザーのプロフィール画像をどのように管理するべきかという点です。アップロード処理や画像の配信方法など、悩むべき点は多数あります。
今回はそういった方に向け、プロフィール画像を管理するベストプラクティスをまとめてみました。
紹介する内容は、私が運営しているWebサービス、「Devicebook」でも使っている技術になります。
概要としては以下の2点です。
- Lambda@Edgeを使ってリアルタイムリサイズ配信
- canvasを使ってブラウザ側で画像リサイズ
リアルタイムリサイズとは
まずリアルタイムリサイズについて説明します。具体例として、以下の2つの画像を見てください。
https://images.devicebook.me/user-profile-images/31-5a65c261ecb41.jpg?w=100
https://images.devicebook.me/user-profile-images/31-5a65c261ecb41.jpg?w=150
URLのクエリにw=100
とつけるだけで画像の横幅をリアルタイムにリサイズできています。(試しに適当なサイズを指定してください。)
このリアルタイムリサイズにより、サーバー側で画像をいくつかの種類にリサイズする必要はありません。
またリサイズされた画像はCDNのエッジサーバーにキャッシュされるため、リサイズが行われた画像は2回目以降、高速にエッジサーバーから配信されることになります。
AWSを使いリアルタイムリサイズを行うためには、CloudFrontとLambda@Edgeを用います。
CloudFrontとは
CloudFrontは、AWSが提供しているCDNサービスです。CloudFrontで画像をキャッシュさせておくことで、CDNのキャッシュサーバーから高速に配信されます。また画像を保存しているS3やWebサーバーなどの負担を軽減させることができます。
AWSのCDNであるCloudFrontは料金もリクエスト数やデータ転送量などを基にした従量課金制です。そのためS3から単純に配信するよりも高速に、そして低コストになる場合が多いです。
Lambda@Edgeとは
Lambda@Edgeとは、CloudFrontの4つの各ライフサイクルで実行できるLambda関数のことです。(下記画像参考)
このLambda関数というのはAWS Lambdaのことで、Lambdaは任意の自分で作成した関数を実行させることができるAWSサービスのことです。
Lambda@Edgeによるリアルタイムリサイズは、Cookpadさんの記事でとても分かりやすく解説されています。
AWS Lambda@Edge で画像をリアルタイムにリサイズ&WebP形式へ変換する - クックパッド開発者ブログ
私もLambda@Edgeを本番運用した感想を別の記事で書いているので、参考にしてください。
canvasを使ったブラウザ側での画像リサイズ
次にフロント側でのリサイズの重要性を述べます。
もしユーザーのアップロード画像が数MBあった時、サーバーのメモリを数MB使用してしまい、リサイズ処理なども含めればさらにメモリを使用します。
そういった仕様だと、複数人のユーザーが同時にアップロードすることにより、サーバーのメモリを食い尽くして500エラーが発生する可能性が高くなります。
そのためフロント側であらかじめ正方形にリサイズしたりサイズを縮小してからアップロードすることで、サーバーの負担を減らすことができます。
私のサービスの場合は以下のフローでアップロードを行っています。
- フロント側で画像を正方形にトリミングし、最大500pxにまで縮小
- PHPのサーバーへ画像をアップロード
- PHP側でS3にアップロードし、ユーザーのデータベースに画像のファイル名を保存
- Lambda@Edgeで任意のサイズにして配信
こうすることでサーバー側の処理はアップロードのみになります。
またcanvasはほぼ全てのブラウザで対応しているため、問題なく使用することができます。
Can I use... Support tables for HTML5, CSS3, etc
canvasでリサイズを行うための方法は別の記事でまとめてありますので、よければ参考にしてください。
Vue.jsでcanvasを使った画像リサイズとアップロードを実装する - Qiita
まとめ
以上が私が個人開発をしていく中で見つけた、プロフィール画像のベストプラクティスです。
もしご意見やご質問がある方は、コメント欄よりお気軽にご連絡ください。