BFF(Backend for Frontend)という言葉を気軽に使っているが、結局なんなのか分かってなかったので、ちゃんと本を読んで理解してみた。
読んだ本
マイクロサービスアーキテクチャ 第2版 単行本(ソフトカバー) - Amazon アフィリエイトリンク
雑な要約
「14 章 UI」の「14.8 制約」以降のまとめ。
前提
デスクトップ Web やモバイルデバイスなどのように、コア機能は同じでも違う UI を提供することがある。
マイクロサービス化の弊害
- UI から各マイクロサービスへの問い合わせが発生する
- → 処理が煩雑になる
- 取得しても不要なデータは捨てることになる
- → 無駄に帯域を使ったり遅延が発生したりする
中央集約ゲートウェイ
これを解消するのが「中央集約ゲートウェイ」。各マイクロサービスへの問い合わせを代行し、一つのデータにまとめ上げて UI に返すというもの。
しかし、複数のチームが単一のゲートウェイを変更する必要が出てくると、チーム間の調整が必要となって開発が遅くなる。また、単一のチームが管理するとなるとそのチームが変更のボトルネックになる。
BFF の登場
これを解消するのが「BFF」。中央集約ゲートウェイとの違いは、特定の UI 用に開発されるということ。
例えば Web ではリストの全件を表示するがモバイルアプリではリストの一部を表示するとき、Web 用の全件返す BFF とモバイル用の一部を返す BFF を開発する。UI と BFF を同じチームが管理することになるので、中央集約ゲートウェイのような問題が生まれない。
ちなみに、デスクトップ Web だけ提供している場合は、マシンリソースがふんだんにあるので BFF は必要ない。一応理にかなうのは、サーバー側でかなりの量の集約が必要な場合だけ。
そして GraphQL へ
クライアント側のクエリを調整するだけで、中央集約ゲートウェイにも BFF にもなる。
※「GraphQL は BFF の実装方法」という記載があったが、管理はサーバー側なので一概にそうとは言えない印象がある。
本の内容を受けて、どうしたらいいのか考えた
最近の流行り
フロントエンド界隈では最近 SWR というものが流行っている。SWR はエンドポイントごとにフロントエンドでキャッシュを持つ。
つまり、ユーザー情報のエンドポイントからデータを一回取得すると、取得した関数がそれをキャッシュして一定時間は Ajax を投げずにキャッシュを返すようになる。個別のサービスへの問い合わせをラップして、煩雑さを軽減している。
ts // イメージ let cache = null let lastFetchedAt = null
export const fetchUserInfo = (userId: string) => { if (cache && lastFetchedAt + 100 < Date.now()) { // 100 秒キャッシュする return cache } const res = ajax.get('/users/' + userId) cache = res.data lastFetchedAt = Date.now() return res.data }
中央集約ゲートウェイと比較
中央集約ゲートウェイのメリットとして、これを叩けばすべてのデータが取得できるという楽さがある。一方デメリットとして、データを個別でキャッシュできなくなるし、データを使い回すために一工夫必要になる。
個人的には SWR のほうが、実際のコードもシンプルになるし制しやすくなると考えている。インフラや BFF のコストも減るかもしれない(実装によりそう)。
わざわざ中央集約サーバーでデータをまとめてから返してもらうようにしておくと、そのデータが必要な画面のエンドポイントすべてを修正する必要が出てくる。UI 都合でサーバーを変更しなければならないので、調整コストがかかる。
だから、マイクロサービス化を進めていったら、UI から個別のサービスに問い合わせて返してもらうようにしたほうがよさそう。
データを追加したことでエンドポイントを複数修正するのが大変なら、GraphQL サーバーにするのがよさそう。サーバーサイドの実装を待たずにフロントエンドの修正が可能になる(正確には GraphQL で返せるようにする必要はある)。
制約を加味して
以上が制約がない場合で、帯域などの制約があるなら GraphQL 一択かなと感じた。
BFF のように個別の UI に対してバックエンドを持つのは、他のサービスへの追従コストが高いように思う。あれば GraphQL にしてしまったほうが楽なのではないか(完全に想像)。
本を読んでの感想
Bad
読みづらい。「Google のソフトウェアエンジニアリング」も最近読んでいるが、同様の感想を持った。リーダブルコードもオライリーだから全部が全部ダメというわけではないが、オライリーの本を読むより別の本を選択したくなる。なお未読のオライリーが数冊こちらを見ている模様。
テキストの構造化が若干ミスっているように見える。「14.9 パターン:中央集約ゲートウェイ」では、これが必要な理由・結果がセクションの最初の方と最後の方に分散して書かれている。テクニカルライティングの基本すらできていないのでは。
また、翻訳が直訳っぽく、日本語を読んでいる感覚にならない。パッと見て出てきた例を挙げておくと、「14.9.4 中央集約ゲートウェイを使う場合」の最後の段落より引用。
それでも、バックエンドで集約、フィルタリングを行いたいと考え、中央ゲートウェイの所有権モデルに関連する問題を取り除きたい場合、何ができますか。そこで登場するのが、BFF パターンです。
原文が "What" で始まってるんだろうなー、という気持ちにさせてくれる「何ができますか。」という文章が味わい深い。
Good
BFF というものを「サーバーとフロントの間にあるサーバー」みたいな雑な理解しかしていなかったけれど、解像度が劇的に上がった。
特に、BFF は UI に依存するものだと分かり、さらに「中央集約ゲートウェイ」からの「BFF」、そして「GraphQL サーバー」と段階を踏んでいることが理解できたのが大きい。「1 つの体験、1 つの BFF」という指針が分かりやすい。
また、本の構成として、あとがきにすべての要約がされているのが助かった。とりあえずここだけ読めばよくて、深堀りしたかったら本編に飛んで読めばいい。詰まっている内容とこの要約があるので、4,400 円は安い。