こんにちは
株式会社HRBrainでフロントエンジニア(とバックエンドエンジニア?)をしているみつです!
スキーマを考えている時に、application/json
とmultipart/form-data
のどちらにするかで悩みました。
最終的には、application/json
とmultipart/form-data
それぞれにメリット・デメリットが存在するため、場面に応じた使い方をしないといけないな!となった過程を残しておきたいと思い記事にしました!
背景
- IDに紐づくPDF等のドキュメントファイル(以降、ドキュメントと記載)をアップロードしたい
前提
- ドキュメントは複数送る可能性がある
- 1つあたりのドキュメントアップロード上限は、20MB〜30MB程度とする
- フロントエンドのコード生成には、
orval
というライブラリを使用している
を満たすスキーマを検討していました。
検討した方法(4案)
検討した方法は、4案でした。
- [1案] APIは1本で、
application/json
でデータを送信(ドキュメントはbase64
に変換) - [2案] APIは1本で、
multipart/form-data
でデータを送信(ドキュメントはbinary
のまま送信) - [3案] APIを2本作り、
application/json
とmultipart/form-data
でそれぞれ送る - [4案] APIを2本作り、どちらも
application/json
で送る
それぞれのメリット・デメリットも考えてみます。
[1案] APIは1本で、application/json
でデータをすべて送信(ドキュメントはbase64
に変換)
メリット
- 1つのAPIですべてを送ることができる(1本だけで良いので、2本作るより楽)
デメリット
- 1つのAPIですべて送信することになる
- ↑ ファイルが複数ある場合、実行時間が伸びていきそう
- Base64へファイルをエンコード、デコードするため処理時間が余分にかかる
- エンコードすることでファイルサイズが増えるため通信時間も増える
[参考記事]
[2案] APIは1本で、multipart/form-data
でデータをすべて送信(ドキュメントはbinary
のまま送信)
メリット
- 1つのAPIですべてを送ることができる(1本だけで良いので、2本作るより楽)
- ファイルを
binary
のまま送ることができる- ↑
application/json
と比較して、処理時間やファイルサイズの心配をしなくて良くなる
- ↑
デメリット
- 1つのAPIですべて送信することになる
- ↑ ファイルが複数ある場合、実行時間が伸びていきそう
-
multipart/form-data
は、フォームとして送ることになる- ↑ keyの設定などで複雑になる可能性がある
[3案] APIを2本作り、application/json
とmultipart/form-data
でそれぞれ送る
-
application/json
→ それ以外をアップロードする -
multipart/form-data
→ ドキュメントをアップロードする
メリット
- ドキュメントは
binary
のまま送ることができる - それ以外は基本的な
json
形式のまま送ることができる - APIが2本に分かれているのでドキュメントアップロードだけ非同期でCloud Run Jobに任せるなどの選択肢が取れる
デメリット
- APIが2本になるため開発コストが高くなる
[4案] APIを2本作り、どちらもapplication/json
で送る
-
application/json
→ ドキュメントをアップロードするAPI -
application/json
→ それ以外をアップロードするAPI
メリット
- ドキュメントはエンコード、デコードが必要だが、それぞれに責務を分割できているためコードの見通しがよくなる
- APIが2本に分かれているのでドキュメントアップロードだけ非同期でCloud Run Jobに任せるなどの選択肢が取れる
デメリット
- APIが2本になるため開発コストが高くなる
- 「ファイルのエンコード、デコードで処理時間が余分にかかる」「Base64エンコードすることでファイルサイズが増えるため通信時間も増える」は問題として残る
先輩エンジニアに聞いてみる
先輩からのアドバイス①
- スピードがそこまで求められるものではないので、どちらでも良いと思う
- 色々な選択肢があると思うが、フロントエンドが実装しやすい方に合わせて上げるというのも1つの選択肢
- ファイルはファイルのまま(
binary
で)送るのも楽といえば楽
先輩からのアドバイス②
- ドキュメントは複数ある可能性もあるため、ファイルサイズもどんどん増える
- ↑ であれば、API自体を分けた方が良い可能性もある
- 加えてそもそも、
base64
で一緒に送らないといけない理由はあるんだっけ- ↑
base64
にする必要がないなら、わざわざbase64
にしなくても
- ↑
決まった方向性
それぞれにメリット・デメリットはあるようでした。
そして、base64
に変換する必要がなければわざわざ変換しなくても良いのではないかというアドバイスはその通りだなと感じ、フロントからバックエンドに送る時点ではbinary
のまま取り扱うことが良いという判断をしました。
結果的に、APIが2本あるためデータベースに保存が必要なものは保存し、時間のかかる処理は非同期で処理するなどの選択肢も取りやすくなりました。
処理の流れ
まとめ
難しいなぁと思いながら、ない頭をひねって最終的にAPIを2本で実装するという方向性を固めることができました。
他に良い実装があればアドバイスください🙇♂️
おわり。
参考
PR
株式会社HRBrainでは、一緒に働く仲間を募集しています!
興味を持っていただいた方はぜひ弊社の採用ページをご確認ください!
HRBrain文化を一緒に作っていきましょう!