![見出し画像](https://assets.st-note.com/production/uploads/images/65375899/rectangle_large_type_2_834d57489513254abe7fbcb3f6c7411d.png?width=1200)
Now in REALITY Tech #19 チャットの画像/動画はどうやってやりとりしているの?
昨年2020年9月にチャットで画像を送信できるようになり、そしてその半年後の2021年3月には動画を送れるようになりました。
今週の「Now in REALITY Tech」は、このチャット上での画像/動画のやり取りの際に具体的にどういった処理が走っているのかを、サーバサイドに重点的に注目しつつ解説していきます。
また同時に、本来画像送信が出来るようになった後、遅くとも年内にはリリース予定だった動画送信機能が、なぜ2021年3月までリリースが遅れてしまったのかもお話しします。
画像送信機能リリース
ではまず、チャット上での画像送信機能がリリースされた時の仕組みから解説します。
まずこの機能の大前提として、チャット上で画像のやりとりをする際、その画像はプライベートなものである必要があります。要は、送った相手と自分以外に見えちゃいけない、ということです。
ですので、画像送信機能リリース当初、画像データは以下の流れでサーバから各端末へと送られていました。
APIサーバにクライアントが問い合わせを行い、サーバ上でアカウントの認証情報を確認してから、画像データをGoogle Cloud Storage(以下、GCS)から引っ張ってきて直接返します。(画像を送信する際は、逆の手順でクライアントからGCSまで画像データがアップロードされます)
シンプルな実装ですね。REALITY上の画像データは今もこの仕組みでやりとりをしているものが多いです。
この時は特に問題は起こらず、スムーズにリリースすることができました。(多少の不具合はありましたが)
この時は
問題発生
画像送信機能がリリースされて一息ついた後、当初から予定されていた動画送信機能に手をつけることになりました。
画像送信機能と同じ仕組みでリリースするつもりで開発が進められていたのですが、ここで既存の仕組みだと問題が発生することが判明したのです。
それは、「動画データが重すぎて、APIサーバ群のメモリを食い潰してしまう」という問題でした。
ここで、先ほどお見せした画像データのやり取りの仕組みをもう一度お見せしながら、どうしてそのような問題が発生するのかを解説していきます。
クライアントからの問い合わせを受け、認証情報が確認できた後、APIサーバがストレージに必要な画像/動画のデータを取りにいきます。
この時取ってきた画像/動画データは、クライアントに返すまでの間一時的にAPIサーバのメモリ上に保持されます。言い換えると、そのデータのファイルサイズ分メモリが占有されてしまう、ということです。
動画データのファイルサイズは、基本的に画像データの数10倍、場合によっては数100倍以上重いものです。
画像データの時には問題ありませんでしたが、動画データが一時的にでもAPIサーバのメモリ上に乗ってしまうと、大量のメモリを一瞬で食ってしまい、サーバ費用の大増加を招くであろうことが判明したのです。
そこで画像/動画データのやり取りの仕方を根本的に変更する必要が生まれました。これが、チャット上での画像送信機能と、動画送信機能のリリースの間に半年もの期間が空いてしまった理由となります。
新しい画像/動画データのやり取りの仕組み
新しい仕組みとして考えられたのは、クライアントが直接GCSから画像/動画ファイルを取得する、という方法でした。
しかし、この方法は前述の「チャット上でやりとりされる画像/動画データがプライベートなものでなければならない」という前提に矛盾します。その画像/動画データのURLを手に入れさえすれば、データを送られたユーザではないのにも関わらず勝手にデータを見れてしまう、ということです。またこの方法だと、URLを手に入れた第三者が勝手にファイルの内容を変更してしまうことも可能になってしまうのです。(自分が送った画像が知らないうちに別の画像にすり替わっていたら…、想像もしたくありません)
そこで、新たにGCSの機能である署名付きURLを活用することとなりました。
署名付きURLは、GCS のドキュメントで以下のように説明されています。
署名付き URL は、リクエスト時における制限付きの権限と有効期限が設定された URL です。署名付き URL のクエリ文字列には認証情報が含まれているため、認証情報を持たないユーザーでもリソースに対して特定の操作を実行できます。
ここで重要なのは、署名付きURLとは「制限付きの権限と有効期限が設定された URL」であるということです。
この機能を使えば、APIサーバ側で認証情報を確認した後、「後からURLを知っても使えない、勝手に画像を更新することもできない」読み取り専用の一時的なURLをサーバ側が発行することができます。(アップロードの際は、更新権限だけを付与した署名付きURLを発行します)
この機能を取り入れた、新たな画像/動画データのやり取りは以下のようになります。
この仕組みは、動画のやり取りだけでなく、すでにリリースしていた画像のやり取りでも活用することになりました。その結果開発期間は大きく伸びましたが、画像/動画データがAPIサーバ上を直接経由しない、よりサーバ負荷の低いセキュアなデータのやり取りを実現することができました。
また、この仕組みを実装するに当たって、以下のGoogle Cloud ブログ上のポストが大きく参考になりました。署名付きURLについてより詳しく知りたい際には、参照してみてください。
最後に
今週は、チャット上での画像/動画データのやり取りの仕組みを、当時の開発秘話を盛り込みつつ、解説いたしました。
今後もお客様の意見を取り組みつつ、より快適で使いやすく、皆さんに愛されるアプリを作っていきます。
REALITY では一緒に開発してくれるメンバーを大募集しています! まずは気軽にカジュアル面談も受け付けていますので、お気軽にお申し込みください!