Open1

デフォルト画像の取り扱い

akira108akira108

よくある、「ユーザーのプロフィールにデフォルトではplaceholder的な画像(Twitterの卵の画像みたいな)があるが、ユーザーは自分で任意の画像をアップロードして差し替えることができるやつ」を実現するための方法がいくつかあるので、まとめてみたい。

TL;DR;

割と当たり前の結論になってしまうが、案1か案2かなあ。案2がnon nullにできるから好きだけど、あとで変えたくなる気持ちを考えると怖い。

前提

いくつか前提条件を決める。実装の都合である程度は変更しても良いものとする。

  • 画像自体はS3のようなストレージにアップロードし、アップロードするとそれを表す識別子が発行されるとする(imageIdと呼ぶ)
  • そのimageIdを、usersテーブルのimage_id varchar(255)みたいなカラムに保存することによりユーザーは画像を設定できるものとする
  • GET /users/1 みたいなAPIリクエストのレスポンスで、imageIdからURLを生成しJSONで返すものとする
  • クライアント側でそれを表示するものとする。
  • 複数のデフォルト画像(うさぎ、かめ、くま、…)があり、ユーザーによっていい感じに設定しておきたいかも?
{ "user": { "id": 1, "imageUrl": "https://example.com/images/:imageId" } }

案1

image_idカラムでNULLを許容する。DBに取得しに行きNULLだったらデフォルト画像のimageIdをアプリケーションサーバーを定数で持っておき、それを返す。

利点

  • アプリケーションサーバー側では似たような処理をいろんなところで書くか、そうならないようにutil的なのに切り出す必要がありそう。nullで返さないように気をつけないとアプリがNullPointerException/Unwrapping nil value的なのでクラッシュする恐れ。
  • 後からデフォルト画像自体のデザインがサービスリニューアルなどで変わった場合にも定数を変えれば一斉に変わる。
  • クライアント側は何も気にせず渡ってきたJSONのURLを表示するだけで済むし、Optionalとして扱わずに済む。

欠点

  • カラムでNULLを許容すること自体をできれば避けたい
  • デフォルト画像を複数用意したいみたいな場合には工夫が必要になる
    • ユーザーIDなどユーザー固有の情報をmodなりしてデフォルト画像を割り振るとか?
    • デフォルト画像ID columnみたいなのを作る?(overkillっぽい)

案2

image_idカラムにデフォルト画像のIDを入れる。

利点

  • image_idカラムをNOT NULLにできる
  • 複数のデフォルト画像を入れる時もINSERT時に選んで入れておけば良い
  • クライアントは表示するだけで良い

欠点

  • 後から変えたくなったら一斉にUPDATEかけるしかない

案3

image_idカラムでもNULL許容して、クライアントにはnullをそのまま渡す。クライアント側でnullだったら、元々バンドルしているプレースホルダー画像を使う。

利点

  • めちゃ細かいけど通信量を減らせる
  • サーバー側らく

欠点

  • デフォルト画像を変えたかったらアプリのアップデートが必要になる(クライアントがネイティブアプリの場合)
  • クライアント側が条件分岐がいる
  • これもカラムでNULL許容

案4(やっちゃダメ)

デフォルト画像をクライアント側で持っておいて、登録時に画像をユーザーがカスタマイズしなければ、デフォルト画像をアップロードしてしまう。

利点

  • 登録後は何も考えなくていい

欠点

  • デフォルトの人の数だけ同じ画像が大量にアップロードされる。ありえないと思いましたか。どこかでみたことがあるんですよね…
  • デフォルト画像を変えたかったらアプリのアップデートが必要になる(クライアントがネイティブアプリの場合)
  • というかアップロードされるたびに別のIDで画像がたくさんできるので後から変えることはほぼ不可。