📖

会員登録時の画像アップロード処理を改善した

2024/11/26に公開

概要

現在toBtoC向けの予約システムを開発しています。

  • toBとは「予約システムを導入しているサロン企業様」
  • toCとは「サロン企業様にいらっしゃるお客様」
    です。

予約システム利用前に、利用者は必ずこのページに遷移して会員登録を行います。
会員登録フォームに 「スマホで撮影した身分証明書」 を添付して送信してきます


イメージ図

想定より検討すべき点が多かったので、今回記事にまとめました。
もっと改善点あったらコメントくださると嬉しいです!🙏

前提

  • RailsサーバーでHTMLを表示するオールドスタイル on Heroku
  • javascriptで直接画像をPOSTするパターンではない
  • 開発者は基本的に私1人のみ。
  • 会員数は3万人
  • 新規会員登録は平均20人/日

対象読者

  • 基本的な機能開発に慣れてきた人
  • 設計についていろいろ考えたい人

いいね!してね

この記事の事例は必要に応じて今後追記していく予定です!
「新しい事例が知りたい」「他の事例も知りたい」と思った人は、ぜひこの記事にいいね👍してください。筆者のモチベーションにつながります!

それでは以下が本編です。

結論

MPAサーバーの場合(今回)

フロントがやること

  • フォームにセットした画像のバリデーション(メタ情報が画像か? 上限サイズ内か?)
  • セットした画像の圧縮処理

バックエンドがやること

  • リクエストパラメータ内の画像のバリデーション(メタ情報が画像か? 上限サイズ内か?)
  • 外部ストレージサービスへ画像をPOSTする(DB処理にtransactionを貼る場合は、最後に処理する)

フロント、バックエンドが別の場合

この記事が一番良いと思いました!
https://future-architect.github.io/articles/20240705a/

説明すること

  • 仕様調査
  • 検討
  • 改善

調査

仕様: シーケンス図

(3)LINEログイン認証後、利用者(Mobile Client)が会員登録ページに遷移します。

(5)利用者は、手持ちのスマホで会員登録フォーム用の身分証明書を撮影します。スマホの画質が良すぎて画像容量が約6MB前後になります。

(7)~(15)サーバー側で

  • バリデーション
  • 画像ファイル容量の圧縮
  • 会員レコード生成
  • 画像ファイルをストレージにPOST

をしていました。

現状の問題点

で、Response Timeが5秒~30秒もかかっていました。

フロント(4G回線で6MB程度の画像ファイルをPOST) これが原因では🤔

サーバー(画像容量圧縮 + 300KB程度の画像ファイルをPOST)

GCS

検討

https://future-architect.github.io/articles/20240705a/
を再度読む。

今回はオールドスタイルRails(MPA)なので、この文脈で検討していきます。

1案 フロントから直接ストレージにPOSTする

フロントから非同期で直接ストレージ(仮バケット)に配置する案。

  • バックエンドが事前に生成した署名付きURLを使う。
    楽なので、あり。 署名付きURLの生成回数に上限はないっぽい。
  • フロントが直接POSTするストレージは仮バケット。
    バケット移動の実装がだるい
    事前にLINE認証処理しているため、ファイルのデータ検証までしなくていい気がする
  • フォーム処理完了後、ワーカーかバッチでストレージ(仮→本バケット)に移動させる
    バケット移動の実装がだるい。ワーカーかバッチの処理を増やしたくない。
  • POST処理に失敗して離脱すると仮バケット内にファイルが滞留する。
    定期的に削除する(削除しなくても直ちに問題にならない) あり。

→面倒なので「一旦なし」と判断。

2案 フロントで画像を圧縮する

サーバー側の処理時間が減るので、あり
※ただし、この程度ならライブラリ入れないで実装する。

検討結果

コスパ重視で2案を採用しました(2案は1案と共存できますし)

改善

実装

(8)の画像圧縮の処理をフロント側で行うようにしました。

結果

平均10秒以下に収まったように見える🚀
※昨日リリースしたので、一旦経過観察中。

最終的にResponseTimeが3秒以内になると期待していましたが、5秒程度が多い結果になりました。
どこがボトルネックになっているか詳細は改めて調査します。

まとめ

Response Timeの閾値10s以内に設定していたら、頻繁にアラートが飛んできてました。
機能開発優先で、場当たり的な実装をしてきてしまったツケでしょうか。

最近、外資系転職対策教材でシステムデザインパターンを見るようになりました。
頻出する)API設計のベストプラクティスをまずは頭に入れて、個々の実装で臨機応変に対応していきたいですね。


この記事の事例は必要に応じて今後追記していく予定です!
「新しい事例が知りたい」「他の事例も知りたい」と思った人は、ぜひこの記事にいいね👍してください。筆者のモチベーションにつながります!

Discussion