SREチームの下野です。
以前こちらの記事で紹介したリアルタイム画像リサイズAPI に対し、 その前段で EXIF情報除去(および画像の回転補正)を行う仕組みを追加する対応を行いました。
今回はその対応や検討の経緯を紹介させていただきたいと思います。
tech.synchro-food.co.jp
前提
リアルタイム画像リサイズAPIとは
以下のようにCloudFront 、API Gateway、Lambda、S3(Public Bucket)を組み合わせて動的に画像をリサイズするAPIです。
弊社の各サービス共通で画像のリサイズに使用しています。

リアルタイム画像リサイズAPIの処理内容は以下の通りです。
- ユーザーがCloudFrontにリクエストを送ります。初回リクエストはCloudFront上にキャッシュが無いため、CloudFrontはオリジンとして設定しているS3のResizedBucketにリクエストを流します
- CloudFrontから流れてきたリクエストを受け、S3はBucket内を探しますが、Resizeされた画像が存在しません
- 画像が存在しない場合、307レスポンスが投げられます
- CloudFrontはS3からの307のレスポンスをそのままユーザーへ戻します
- ユーザーは307レスポンスを受け、次は画像変換APIのURLを待ち受ける、APIGatewayにリクエストを投げます
- API GatewayよりLambdaの画像変換関数がキックされます
- LambdaがS3のOriginalBucketより、画像リサイズ元となる画像を取得します
- 7で取得した画像をパラメータに従ってリサイズし、ResizedBucketに保存します
- 8で保存した画像へのURLへの301レスポンスをLambdaにて返します
- 301レスポンスをそのままユーザーに返します
- ユーザーは301レスポンスに従い、もう一度リサイズ画像のリクエストを送ります
- CloudFrontからResizedBucketにリクエストが流れ、変換後画像をレスポンスとしてキャッシュしつつ、結果をユーザに返す
詳細はこちらの記事をご参照ください。
EXIFとは
EXIF(EXchangeable Image File Format)とは、デジタルカメラやスマートフォン等が JPEG や TIFF(一部 HEIF 等を含む)に埋め込むメタデータ規格です。
撮影日時や、端末・カメラの機種、 位置情報、画像の向き情報などを保持しています。
EXIF情報を保持した状態で画像を公開すると、悪意のある利用者によって写真を撮影した際の位置情報等から個人情報の特定につながる可能性があり、削除しておいたほうが安全です。
また、EXIFは画像の向き情報を保持しており、EXIF情報を除去すると画像の正しい向きがわからなくなる場合があるため、EXIF情報を除去する際は除去前に画像の向きの補正をする必要があります。
背景
これまでリアルタイム画像リサイズAPIの構成では、使用しているS3がPublic Bucketのため アップロードされた画像がEXIF情報を保持している場合、EXIF情報ごと画像を公開してしまう可能性がありました。
そのため、リアルタイム画像リサイズAPIを使用する前に、アプリケーション側でEXIF情報を除去して画像をアップロードしていました。
しかしアプリケーション 経由のアップロードでは、 画像が大きい場合に時間がかかることや、EXIF除去の処理がアプリケーション側の性能劣化に繋がる等の課題がありました。
これらの課題に対応するため、リアルタイム画像リサイズAPIを利用するアプリでは、ユーザーから直接 S3 へアップロードするような対応を検討していましたが、その場合これまでのようにEXIF情報をアプリケーション で削除できなくなる問題がありました。
リアルタイム画像リサイズAPIは各サービス共通で利用されているため、EXIF情報除去についても同じように利用できた方が良いため、機能を追加することになりました。
対応内容
構成の検討
方針
チーム内で構成を検討したところ、リアルタイム画像リサイズAPI へ以下のような仕組みを追加する方針になりました。

追加する仕組みの処理内容
- クライアントからプライベートS3へ画像をアップロードする
- S3からLambdaへアップロードイベントを通知する
- Lambdaが Private Bucketから画像をダウンロードする
- 画像の向き補正・EXIF情報除去を実行する
- 処理済みの画像をリアルタイム画像リサイズAPIの Original image bucketへ保存する
構成検討の経緯
以下の理由で既存のバケットを Public から Private に変えられないため、EXIF除去前の画像を公開していない場所で受け取る必要があり、ユーザーからの画像アップロードを受け取るPrivate Bucketを追加する方針になりました。
なお、Private Bucket にアップロードされたEXIF情報がある画像はS3のライフサイクルポリシーによって削除しています。
- Original image bucket
- EXIF情報が残っている画像ファイルが公開されないようにする対応であるため、単にリアルタイム画像リサイズAPI のOriginal image bucket をPrivate Bucketにできないかを考えましたが、Original image bucket内に公開している画像が存在したためできませんでした。
- Resized image bucket
- リアルタイム画像リサイズAPIは、リサイズ後の画像を保存するバケットでリサイズされた画像がない場合にリダイレクト処理を実行 しています。リダイレクト処理は、S3の 静的ウェブサイトホスティング機能 とリダイレクト機能を使用しており、Privateに変更するとリダイレクトが動作しなくなり、大規模な改修が必要になると想定されたため、実現したいことに対して影響が大きくこちらの設定変更での対応は難しいと判断しました。
EXIF除去処理の実装
EXIF除去を行う処理は、Pythonで実装しました。
画像の向き補正、EXIF削除にはWand(ImageMagickのPythonバインディング) を使っています。
Wandにした理由は、社内でImageMagickの利用実績が多かったためです。
以下の通り処理自体は比較的にシンプルなため、それほど苦労せずにコードを作成できました。
- Private Bucketから画像をダウンロード
- 画像の向き補正、EXIF情報除去
- 処理済みの画像をOriginal image bucketへ保存
しかし、性能面の調整に苦労をしました。
前提として、リアルタイム画像リサイズAPI の前段に処理を追加する構成であるため、高速に処理する必要がありました。
初めはコスト最適化を意識して Lambdaに搭載するメモリは 1~2GB(1792MB/2vCPU)で開始しましたが、以下の課題があることがわかりました。
- 画像の最大サイズと想定している20MB の画像でメモリが足りないことにより Runtime Exitエラーが起きる
- 画像のサイズを大きくしていくとImageMagick の処理に時間を要し、処理時間が 3 秒以上かかる
性能面の課題への対応 1
まずは、課題の1点目の対応をしました。
処理が正常終了しないと本番運用できないため、まずはRuntime Exitエラーが起きないようにLambdaのメモリを4096MB(3vCPU) に増やしました。
メモリを4096MB(3vCPU) に増やしたところエラーは起きなくなり処理性能も一定の向上があったものの、画像のサイズによっては処理時間が 3 秒を越えやすい状況でした。
性能面の課題への対応 2
2点目の課題への対応です。
最初は、1点目の課題への対応と同じく Lambdaの vCPU/メモリ の量を増やすことで改善が図れないかと考えました。
Lambdaの割当メモリを増やすことでの懸念はコストですが、Lambdaは実行時間に対してコストが発生するため、処理性能が良くなるのであればコストは大きくは増えないと考え、かける労力が少なく対応出来ると良いかと思ったためです。
効果があるかを確認するため、一旦 Lambdaの割当メモリを 4096MB -> 8192MB(5vCPU)にして試しましたが、処理時間にはごくわずかな差 しかありませんでした。
次に、ディスクIOが原因ではと考えました。
S3から取得した画像やEXIF情報を除去した画像は、Lambdaの一時ディスク上に保存していたためです。
Lambdaのメモリ上で、EXIF除去・画像の向きを補正するよう修正して試しましたが、こちらもわずかな差しかありませんでした。
性能が上がらなかったことの調査のため実行ログを見ると、ディスク IO が原因ではないことがわかりました。画像の向き補正に時間がかかっていたようです。画像サイズが約 10MB を超えると向き補正に要する時間が増加しており、この処理は Lambda の割当リソースを増やしても改善されないものでした。
その後もImageMagickの依存ライブラリの変更などを試したのですが、あまり効果はなく画像のサイズによっては処理時間がかかるケースがありました。
こちらについては、アプリ側でユーザー向けにアップロード中であることを画面に表示すること、過去の傾向的にサイズの大きい画像はアップロードされるケースが少なかったことから、今回は受容する方針になりました。
振り返り
今回の対応では、無事EXIF情報除去機能を追加することができました。既存の画像リサイズAPIの機能・運用を維持したまま、当初の課題のアプリケーション側での処理を回避するという目的を達成できた点は良かったと思います。
実装面では、Lambdaのメモリ増強や処理フローの見直しなど、性能面の課題にも対応しました。通常サイズの画像では十分な性能を確保できた一方で、大容量の画像ファイルに対しては処理時間が長くなるという課題が残りました。発生頻度や運用上の影響を考慮し、現状では許容することとし、将来的に改善していければと思っています。
性能面の課題への対応では、先にもっと深く調査をしておくべきだったというような反省がありますので次回の対応時に活かせるようにしたいと思います。
まとめ
本記事では、リアルタイム画像リサイズAPI に対し、前段で EXIF情報除去(および画像の回転補正)を自動的に行う仕組みを追加する対応をした経緯をご紹介しました。
この記事がどなたかのお役に立てれば幸いです。




