マイクロサービスの思想から捉える Backends for Frontendsとその類似パターン

qsona
FiNC Tech Blog
Published in
8 min readJun 8, 2018

こんにちは qsona です。LINE株式会社さんの UIT#3 The “Backends for Frontends” sharing のイベントにて、タイトルにある内容で登壇をしてきました。とても良い会にお招き頂いて感謝しています。

以下が登壇資料です。

この記事では、この資料に関する補足を少し行いたいと思います。

BFFと技術選定

技術選定は、それぞれの組織・ビジネス・人など様々な状況を考えて行われるべきです。BFFも例外ではありません。

マイクロサービスを構成していくほどの規模になると、クライアントへのAPI提供が複雑になってきて、アーキテクチャ的にどう解決するのか、課題になってきます。

その答えの1つがBFFなのですが、技術選定としては「BFFを作るか作らないか」のような単純なものではありません。様々な背景を理解し、BFFを作るのか、作るなら何の言語なのか、役割は何をもたせるのか、誰がメンテナンスするのか、どんな設計にするか、APIはRPCなのかRESTなのか、etc… と、様々なことを考える必要があります。特にBFFはまだ歴史も浅く、決定版のようなパターンはないので、技術選定者の腕の見せ所になります。

FiNCでは長い間、この問題から目を背けて・・・いたわけではないのですが、実際にはしばらくBFFやAPI Gatewayを設けず、2016年末にBFFを作ってからも、アプリ全体の1割未満のリクエストに利用をとどめていました。

一方で、他の種々の改善はずっと進めていました。

まず、Backend APIの改善です。APIの提供の仕方は、2016年中旬ごろから1年間ほど、様々な議論やライブラリの整備等に力をいれていました。これにより、開発者のAPIに対する認識がそろい、再利用性の高い良いAPIが作られるようになりました。

また、iOS/Androidアプリのアーキテクチャ改善も進んできました。FiNCアプリはiOSもAndroidも基本的に同じ機能を提供しているにもかかわらず、2016年まではそれぞれのチームが別々にアプリを作っている状態で、アーキテクチャやドメインモデルの捉え方が微妙に異なっているなどの問題が起きていました。2017年は「Client Fusion」を合言葉に掲げ、まずは設計時のコミュニケーションを多く取りドメインモデルの認識を揃えるところから、徐々に2つのアプリのアーキテクチャの全体像も揃えていきました。これにより、OS間の違いによる障害が減り、生産性も向上していきました。

もう一つ重要だったのが、組織の改善です。FiNCアプリチームはもともと、iOS/Android/Serverと技術軸でチームが分かれていたのですが、諸々の経緯の後、ビジネスの単位で4つにチームが分かれ、各チームにそれぞれiOS/Android/Serverのエンジニアが入っているという体制になりました。これにより、機能ごとに職種間のコミュニケーションが促進され、エンジニアもチームのKPIが追いやすくなりました。これによりチーム単位でビジネスを進められるようになり、マイクロサービスの利点も以前よりもずっと大きくなりました。

BFFというアーキテクチャの本格導入を、こういった様々な改善まで待ってきたことは、今考えると間違っていなかったように思います。もちろん全てできるに越したことはありませんが、使えるリソースも限られているて、優先順位の問題もあります。BFFは正しい使い方をしないと「単に複雑さと実装工数が1つ増えている」状態になりかねず、自らの足を引っ張る危険性もあります。

バックエンド・クライアント・組織が正しい状態に向かっており、いよいよ今回BFFを再設計して本格的な導入を目指す流れになりました。それが発表資料3章で紹介した、gRPC/Kotlinを利用したBFFです。まだまだ未検証のことも多いですが、以前に比べて条件が整っていますし、検証を進めながら良い技術選定をしてきたいと思います。

この項を書いたきっかけは、BFFは(マイクロサービスと同じく)いきなり盲目的に導入してよいアーキテクチャではない、ということを伝えたかったことです。どんなアーキテクチャにも言えますが、様々な背景の上で、きちんと理由を持って技術選定するのが非常に重要だと思います。

Micro Frontends

3章の後半で Micro Frontends の話をしました。これについて懇親会で Yosuke Kurami さんと話すことができて、自分にとって非常に有意義でした。ざっくばらんに話していましたが、以下の2つがポイントだったかなと思います。(以下の内容は後日qsonaが個人の考えを付加してまとめているので、文責はqsonaにあります。)

Micro Frontends と BFF のハイブリッド手法 … Micro FrontendsはUXの一貫性などの理由で難しいという説が強くあり、実際私もそう思うのですが、ハイブリッドな手法にすれば導入しやすくなるのでは、というのを私の発表の最後で投げかけました。これについて少し突っ込んで話させてもらい、実際UIの種類によってMicro Frontendsが導入できるところとBFFが適切なところがあるよね、という話になりました。

具体的には、ある画面のヘッダーのコンポーネントでは、1つの切り離しにくいUIに様々なサービスの情報を集約しており、このようなケースではBFFでAPI集約するパターンが適しています。一方で、画面ページ中のあるUIコンポーネントは基本1つのサービスの情報をそのまま利用できるとしたら、サービスがUIコンポーネントを返すMicro Frontendsのやり方が適用できます。このように、適材適所で導入していけば、比較的やりやすいのではないでしょうか。

1つの懸念は、いまBFFで集約している場合、この手法に移行したときにAPIリクエスト数が多くなる可能性です。いま画面全体で1つのAPIリクエストにまとめている場合、上の手法にすると、2つのUIコンポーネント(を司る、例えばUse Case層)で別々にリクエストを飛ばすことになり、リクエスト数が増えます。しかし、Use Case間で同じAPIを利用しているなら、キャッシュを利用することで回避できますし、そうでなくても、むしろ別々のリクエストにすることで独立にレンダリング開始できるメリットもあります。アーキテクチャとしてもそちらのほうが良いと言えるでしょう。

Micro Frontends は Microservicesのアナロジーで考えられそう … Micro Frontendsでは、各UIコンポーネントがCustom Eventsを飛ばし、それを別のUIコンポーネントがハンドリングするという、イベントドリブンな方法で連携できます。これと似たことはまさにMicroservicesがバックエンドで行ってきた、非同期イベントをキューに永続化してそれを実行する、という非同期アーキテクチャに似ています。したがって、バックエンドでやってきた手法を使える部分もありそうです。

また、たとえば各UIコンポーネントが、クライアントアプリケーション共通のモーダルを出したいときはどうでしょうか。おそらくモーダルはClientの持ち物で、各UIコンポーネントからモーダルを出したいという要求を調停する役割を担います。例えば、あるUIコンポーネントからUIモーダルを開きたいイベントが来たが、すでに別のコンポーネントによっとモーダルが開かれているとき、新しいモーダルを無理やり開くのか、キューに積んで待つのか、などを決めます。

バックエンドでは主に、結果整合性の概念を使います。分散環境でのトランザクションを諦め、代わりに最終的に正しい状態になればよい、という考え方です。フロントエンドの場合、最終的に行われないときがあっても、そこまで問題ない動作もあります。バックエンドで結果整合性が担保されていれば、最悪でも画面を更新すれば、正しい状態が担保されるからです。

FiNCではバックエンドで非同期イベントのアーキテクチャを導入した後、それが一種のマイクロサービスのインフラのようになり、網目状にサービスが連携していく流れができていきました。フロントエンドでもそのような状態が作れたら面白いのですが、上述したUI・UXの一貫性の問題は非常に大きく、どこまでそういう世界感にできるのか?は興味深く、今後チャレンジしていきたいテーマです。

全体を通して

BFFという、長い期間色々考えてきたテーマについて、とても素敵な場で発表させてもらえて大変光栄でした。お声がけいただいた @kawasako3 さんはじめ、LINE株式会社のスタッフの皆様に感謝しています。

FiNCでは今ネイティブアプリ向けのBFFを絶賛開発中です。また発表では触れられませんでしたが、Web向けのSPA+SSRのNode.jsサーバをBFFとして活用していこうとしています。興味を持っていただける方はぜひ、 Wantedly 等で気軽にお声がけ下さい!

--

--

qsona
FiNC Tech Blog

株式会社FiNC所属, WebエンジニアNode.js/Ruby, Rails