フロントエンドはマイクロサービス化の恩恵を受けられるのか? — Micro Frontends パネルディスカッションレポート(前編): Microservices Meetup vol.7

こんにちは、qsona (twitter) です。FiNCでは先日 2018/7/31 に Microservices Meetup vol.7 (Micro Frontends) を開催しました。

本イベントでは、teppeis さん, Yosuke Kurami (Quramy) さん, Suguru Inatomi (lacolaco) さんの御三方にご協力いただき、約1時間にわたりパネルディスカッションを行いました。様々な論点について議論が及び、とても充実した内容になりました。ご協力いただき、とても感謝しています。ありがとうございました。

本記事では、この中で行われたディスカッションの内容の大筋を書き起こし、また、最後に簡単な総括をしたいと思います。なお、本記事は100%正確な書き起こしではなく、編集を行っております。意図を損なわない努力をしておりますが、文責は qsona にあることを明記しておきます。

なお、この記事は前編です。後編はこちらからご覧ください。


イントロダクション

qsona: 議論に入る前にまず、ご登壇者の自己紹介をいただけたらと思います。

lacolaco: 株式会社Kaizen Platformから来ました、らこといいます。フロントエンドエンジニアやってます。主にAngularを書いています (筆者注: lacolacoさんはAngular Japan User Groupの代表)。一度、Kaizen Platformの神保が Web Components で 社内 UI ライブラリを作っている話 をしていて、その話前提に話すかもしれないので、それを見ておいてもらえると話が早いです。よろしくお願いします。

Quramy: Quramyといいます。株式会社FOLIOというネット証券の会社でフロントエンドをやっている人です。僕も何ヶ月か前まではAngularを書いていたんですが、最近はReact+Reduxで大きいモノリシックのフロントエンドをやっています。

teppeis: teppeisといいます。サイボウズ株式会社からやってきました。今日はみんな株式会社ってちゃんというタイプですね(会場笑) サイボウズはグループウェアとかkintoneとかを作っているんですが、私はプロダクトを作るエンジニアはもうこの1,2年くらいはやってなくて、組織マネージャー等をしばらくやっていました。最近またプロダクトに関わり始めています。なんでここにいるかといいますと、2年くらい前にあったMicroservices Meetupの第1回で、いきなりマイクロフロントエンドという文脈がぶっ飛びすぎた発表(slideshare: Web Frontends of Microservices)をして、そのよしみで呼ばれました。そんなにその後マイクロサービスとかマイクロフロントエンドを実践しているというわけではないんですが、組織的な話とか割と好きなので、そのあたり話せたらいいなと思います。

各組織・プロダクトにおけるMicro Frontendsのモチベーション

qsona: ありがとうございます。そもそもマイクロフロントエンドは新しい話なので、今日は話をまとめにいかなくても発散しなくても良いかなと思っていて、どんどん燃料を投下しながらやっていけたらなと思っています。最初はWhyの話からはいったほうがいいかなと思うので、各社、組織/プロダクトにおいてマイクロフロントエンドどれくらいやりたいというモチベーションがどれくらいあるか、その理由の話からスタートしたいと思います。

lacolaco: Kaizen Platformのモチベーションとしては、フロントエンドの人数は少ないんですが、バックエンドはすでにマイクロサービス化していて、新しく作るプロダクトがいくつかあったときに、別々のプロダクトを3人で3つ、個人戦でそれぞれプロダクトを作るということが発生していて、そこにUI・UXの統一をしつついい感じにやるにはどうしたらいいかという問題があり、コンポーネントを社内UIライブラリにして切り出していこうとしたのが始まりです。

それが進んでいって、マイクロサービスがあるんだからそれに紐付いたフロントエンドあると楽じゃない?ということに気づき、マイクロフロントエンドというのを後から知って、これじゃん、となった感じです。なので、マイクロフロントエンドという名前は最近知ったのですが、似たようなことをやろうとしていました。

Quramy: FOLIOでもバックエンドはマイクロサービス化がすすめられていて、独立したチームで機能開発をしています。そっちを眺めていると、いろんなリポジトリがあって小さい単位で開発できていて、うらやましいなと。

一方フロントエンドは一つの大きいモノリシックになっています。フロントエンドの人数は5人で、SPA的なプロダクトの中で5人というのは割と多い方なのかなと思います。その中で、例えばReduxのミドルウェアを変えたい、のような、全体の方針を変えるような決定をしようとすると、全員の合意を取る必要があるのはもちろんですし、既存のコードをどうやって全部移行するのかというのを考えなければならない。フロントエンドのライフサイクルは短くて、これを使わないほうがいいよねという判断が2年後に走ったりする世界なんですが、そこで大きいモノリシックなリポジトリをメンテナンスしていくのがしんどいなと。

具体的な例でいうと、コードがすごく多いのでCIの時間がすごくかかってしまうとか、個人的にはFlowよりTypeScriptがすごく好きなので置き換えたいんですけど、Flowのコードが山のように入っていて微妙に移行できない、ということがあります。いろんな技術選択ができるよね、という話がさっきのFiNCさんの話でもあったんですが、そこが大きなモチベーションで、具体的にどういう分割というよりは、リポジトリを小さくわけたいということに一番モチベーションがあって、マイクロフロントエンドというところで紹介されたり整理されている技術機構が役に立てられたらいいなあというところです。実践とかは全然していないんですが、それは両側の方に・・・。

teppeis: 2年前に出した資料を見てもらえると文脈が書いてあるんですが、サイボウズではプラットフォームとしてcybozu.comという共通の基盤があり、その上にサイボウズのプロダクトが3,4つ乗っている形になっています。複数のプロダクトがある中で、そこに共通のパーツ、例えばヘッダーの部分で共通のパーツがあるとか、サービスのアップデート情報とかお知らせ情報とかは複数のサービスで同じ、等のことがあります。

特に、お知らせ情報では、お知らせを管理しているサービスがあって、それをいろんなプロダクトにUIとして出したいという、UI込みの独立したサービスが出てきますが、現実的にそれをいろんなプロダクトに出していくにはどうしたらいくんだろう、というのが。2年前のマイクロサービスという話が盛り上がってる時の「これUIの話全然ないじゃん」みたいな疑問でした。

その後それをどうしたかというと、振り返ってみると「そんなに分けることないな」という気がしてきています。(会場笑) そういう場面はあることは間違いないんだけど、そんなにそこが問題になるほど分けるわけでもないのかもしれない、という感じになってきています。

複数プロダクトにおけるUIの共通化

qsona: せっかくパーツの共通化という話が出てきたので、そこからいきますか。サイボウズの中だとどうしているのですか?

teppeis: バックエンドのサービスがいわゆるREST的なAPIを提供して、フロントのプロダクトがAPIを叩いてUIを作っています。最初は共通のUIを出そうとすごい頑張ろうとしていたのですが、結果的に、サービスごと、プロダクトごとに求めているものが違ってきて、共通化しようというモチベーションがほとんどなくなっていきました。UIも変わってきたし、プロダクトごとに違うところもあるので、一緒にする必要ないじゃんという。それぞれのプロダクトごとに適した見せ方をすればいいよねという感じになってきて、当初言っていたところに関しては、共通化されませんでした。

qsona: 確かに、僕の最初のトークでも一個のプロダクトとして見せるというのを前提にしていたのですが、マイクロサービスを進めていると、プラットフォームとして提供しているうちにプロダクト自体が別になるということはよくあるのかなという気がしていて、納得感がありました。

lacolaco: うちでいうと、そもそもプロダクトを複数あって、テーマを共通化する必要がありました。ブランド感を出すためと、ユーザがプロダクトを渡ったときに同じ世界観を維持するために、トップのヘッダーなどは一番最初に目に入るのでそこをまず統一しなきゃいけないとか、サービス間を渡すメニューがあるのでそこのリンクの出し方を統一するとか、必要ベースで進めていきました。

qsona: 進め方迷うのですが、具体の話に踏み込んだほうが面白いですかね。(ひよりながらteppeisさんにバトンを渡す)

teppeis: 最初はテクニカルな話をしていきますか。共通化とかをやったときは、どういう境界で、どういう技術を使って、何と何を共通化しましたか?

lacolaco: まず、技術的にはWeb Componentsを使いました。生のCustom Elementsとlit-html (github: Polymer/lit-html) を組み合わせてやったという感じです。UIライブラリ化したものは、アプリケーション内で使うアイコンのコレクション、ヘッダー、メニューのリスト(よくあるマテリアルデザインっぽいもの)、アバター、アプリケーションのタイトルを出すところなどです。

ヘッダーより下のアプリケーションの中の部分にはあまり触っていないですね。触っているのはフォントくらいです。アプリケーションコンテナのような全体のコンポーネントに、フォントなどのテーマを入れています。その中にReactやAngularのrootのコンポーネントが置かれている感じです。

バックエンドロジックまで含まれている共通UI

teppeis: マイクロフロントエンドみたいな話と、UIの統一みたいな話があって、単純なUIの統一だけだったらスタイルガイドみたいな話になるのかなと。マイクロフロントエンドと言ったときは、そこにバックエンドのサービスがあって、というところが一番の違いかなと思うんですが、いま言っていた話ってアイコンとかメニューなどのスタイル統一の話で、マイクロフロントエンドの話とはちょっと違ったところもあるのかなと思ったのですが。

lacolaco: わりとそんな感じはします。うちでやってることの8,9割くらいはスタイルガイドみたいな話なんですけど、スタイルガイドどおりに実装するのは毎回骨が折れるので、ライブラリ化しようとなりました。一方で、さっきプロダクトのメニューが出ているといったのですが、ユーザの状態、例えばこのサービスには契約している/していない、によってメニューの一部が出たり出なかったり、変化するのがあります。そのため、バックエンドを意識しながら作らなきゃいけなくなっているのですが、このマイクロサービスが提供してくれよと思い始めたんですね。つまり、各アプリケーションがバックエンドからJSONをとってきてUIライブラリに当てるという形になっていたが、UIライブラリ側がそれをやってくれよという気持ちになってきた。

teppeis: バックエンドサービスにAPIがあって、それに対応するUIライブラリみたいなものを提供していくみたいなスタイル。

lacolaco: はい。それをやるんだったら最初からマイクロサービスがUIを提供してくれればいいじゃん、と。

teppeis: なるほど。それってエンドポイントとしてはどうなるんですか?例えばiframeだったらイメージは簡単で、iframeで普通にurlを叩いて、中身は全部上から下のレイヤーまで1個のマイクロサービスが提供する感じになっていると思うんですが、Web Componentsとなったときにそこをどう指定して通信とかUIから全部提供していくのか。

Quramy: Web ComponentsがAPIを叩くという機能までパッケージングされた、上の例でいうメニューコンポーネントみたいなものをどうくくりだしていくか。

lacolaco: 今はまだなくて今後やりたいねという話になっているのですが、だいたいWeb Componentsでは1コンポーネントで1つのjsか、あるいはコレクションで1つのjsになるか。なのでエンドポイント的には1サービスで1jsかなと。アプリケーション側はそれをインストールしていき、マッシュアップ的になる。

Quramy: 僕の理想的なマイクロフロントエンドのイメージはそういう感じですね。

Menuという、バックエンドからフロントエンドまで統合されたサービスが、APIだけではなく、menu.js のようにMenu Componentを提供していて、それがWeb Componentsなど何かしらの方法でごそっと取ってきて、それを配置するとよしなにMenuが表示される。

パフォーマンスのオーバーヘッド

teppeis: それを、メニューみたいな粒度でやっちゃうとすごいオーバーヘッドがあるというか、1個ごとにjs取ってきて通信が走って、バックエンドとの通信を個別のコンポーネントごとにやるから全体で統一出来ないとか、そういう感じになっちゃいそうです。iframeでやると明らかにそうなるんですけど、そこの部分に対するWeb Componentsの未来への展望はあるんですか?全部のパーツをiframeでやっているとさすがに厳しいなとなるのは想像できるんですが。

lacolaco: iframeが遅いから?

teppeis: そうです。そこはWeb Componentsだったらいける?

lacolaco: Web Componentsだったらいけるかどうかは分からないですが・・・ネットワーク富豪的な感じはしますよね。

jsが分かれて逆にアプリケーションから分離されるので、ライフサイクルが変わるから、CDNのキャッシュの寿命を長く出来てキャッシュが効いてるとかはあると思うので、そこの最適化はあると思うし、アプリケーションjsサイズが下がるとjsのparseの時間が短くなり、lazy loadみたいな。

qsona: http/2になったらある程度解消されたりするんですか?

teppeis: どうでしょう、http/2は基本的に夢を見ないというのが大事で (会場笑)

lacolaco: pushはできるかもしれないですよね。どっちがどっちをpushするのかわからないけど、UIとってくるときにdataをpushしていくのか。

teppeis: first renderingに対する起動みたいなのはちょっときついけど、lazy laod的に後から読むようにするはできると思う。

Web以外のMicro Frontends

ネットワーク富豪的という話があったけれど、前のスライドにも書いたのだけれどMicro FrontendsはPC web特有の考え方なのでは?モバイルでは多分ないと思うんですけど、どうでしょう。モバイルでこういう興味とか課題がありますという方はいらっしゃいますか?

qsona: 僕は結構ありますね。FiNCアプリは明らかに一個のアプリとしてはいろんな機能が盛り込まれすぎていて。

これは2年前teppeisさんが以前話されていたのをよく覚えているんですが、モバイルは1つのアプリで単一機能だから、アプリ分ければいいじゃんということだったと思うのですが、現実的には様々な問題によりそれが可能かどうかという問題はあると思っていて、結局マイページにはいろいろはいっているみたいなことは起きていますね。マイクロフロントエンドとまでいかないにしても、アプリ内でモジュール化しようとかの当たり前の話から、将来的にはAndroid Instant Appとか、普通にCustom URL Schemeのようなものでシームレスに連携できるようになっていけばアプリをどんどん分けられるという話はあると思っていて、そっちはそっちで面白いというか、FiNCはわりとアプリがメインなのでそちらも追っていかなければいけないと思っています。

lacolaco: 粒度の問題な気がして、例えばGoogleのログインはれっきとしたマイクロフロントエンドだと僕は思っています。ログインしようとしたら専用の統一されたログインの画面に行く。あれはmobile/PC関係ないよなと思っていて、ログインのマイクロサービスとフロントエンドがセットになっていると思います。マッシュアップ的な、1個の画面中に複数コンポーネントが出ることはあまりなさそうですが、モバイルでも粒度によっては、画面ごとの単位であるかなという気がしています。

Micro Frontends / Microservices / 組織の粒度

qsona: いまの話で一個質問したいなと思ったのですが、メニュー自体が一個のバックエンドと結びついてないことが多い気がするんですよ。メニューがいろんな情報、マイクロサービスをaggregationしていて、メニューをWeb Componentsで提供したいというモチベーションはすごいわかるんですが、バックエンドと1対1になるかというと、そうとも限らない気がします。(アンケートでも)粒度の話はすごく質問が多くて、どういう粒度でマイクロフロントエンドを提供していくか、サービスと組織とUIが1対1対応になっていればベストだと思うんですけど、その辺はどうですか?

Quramy: それは僕は思うところが最近あってですね・・・。さっきの micro-frontend.org の 説明があったんですが、マイクロフロントエンドの説明のために作られているサービスなので、綺麗に分かれすぎなんですよね。なんかここがこうbackendとfrontendが一対一になっているじゃないか、みたいな。技術的にそんなきれいに分けられるものばかりじゃないと思っています。

これはいま自分がみている例で、ちょっと話飛ぶんですが、Backends for Frontends (BFF) という、 マイクロサービスとフロントエンドをどう統合するかというテーマでよくキーワードになっていますが、FOLIOでもwebに対応したBFFがあります。この中でも、蓋をあけてみると、あるView、うちの場合はReactがあるんですが、そのReactのコンテナコンポーネントを構成させるために、まずBFFのAPIを叩き、BFFがbackendを叩くという二段構成になっています。

で、BFFの層の複雑さが場所によって全然違うんですね。すごいわかりやすいところでいうと、例えば株を買う注文確定するというボタンとかは、BFFのpostを受けるAPIが、そのままOrderみたいなサービスをpostしているだけで、すごくわかりやすい1:1でbackendとfrontendが本当にきれいに対応しています。

一方で、もしネット証券やったことある方とかはちょっと想像してみてほしいのですが、みなさんの資産ってこういう状況ですよというのを表すところ、例えば現金がいくらあります、持ってる株がいくらあります、売ろうとしているものが売れるとこれくらいの金額になります、そんな感じで、それぞれ気になっているバックエンドのサービスが全然違うんですね。これを描画しようと思ったら、最低でもサービスの個数分くらいはAPIを叩いて、フォーマット揃えたり計算できるようにしたりする必要があり、それをBFFがやっています。こういうのは、1対1にするのは絶対に無理だと思うんですね。このBFFの機能は誰かがやらねばならぬし、それは必要だと思っていて、現金を見ているサービスと一対一にするなんてことはできないです。ユーザーがみたいものはあくまで統合されたダッシュボード的なものであって、BFFとUIというセットが生き残るし、組織論的な話をしていても1対1の組織には多分ならないので、そこに無理やりマイクロフロントエンドを持ち込むのは危ないんじゃないかなと思っています。いわゆるマイページ的なところは結構危ないんじゃないかなという気がしています。

lacolaco: 前提としていろんな粒度はあるよね、というのはあります。Componentにもいろいろ粒度があって、UI Componentsをマイクロフロントエンドに含めるんだったら、(筆者注: Atomic Designの) Atoms にあたると思うし、あるいはもっとデータの通信とかする、コンテナ、Decision-Maker的なスマートなコンポーネントになるかもしれないし、ニーズによると思います。

何につけても僕はマイクロフロントエンドを目的化したら死ぬと思っていて、ニーズが生まれてから考えたらいいんじゃない、というようにひたすら踏みとどまっている。これ目的化すると無限にやりたくなって、特にマイクロサービスをやっている会社だと。これインターフェースがメッチャ難しい気がしていて、HTMLの属性何にするか、それで何やるのか、ユースケースに依存すると思うので、基本に立ち返りモジュール化や切り出しというところに重きを置きたい。粒度は僕はわからないです。(会場笑)

teppeis: micro-frontends.orgに関して言うと、読み進めていくと最初の方で The DOM is the APIというのが出てきて、そこでなんか我々DOMに苦しめられてきた世代からすると、いきなり懐疑的な気持ちになる(会場笑)。DOMがAPIだと!?という。

マイクロサービスが最初に出てきたときからの話で、境界が一番大事だ、というのがあります。Sam Newmanのプレゼンとかでも、モデリングはビジネスドメインによってモデリングしないとだめだという話をしていますが、1画面のなかにビジネスドメインが異なるものがどれだけ本当にあるの?というのを個人的には思っています。すごいいろんなビジネスドメインがあるみたいな画面って、Quramyさんが言ったようなマイページ的なものや、ダッシュボード、ポータルのトップページ、というものは確かにありそう。ただ、そこから1個クリックして入ったときに、果たしてどこまでたくさんのビジネスドメインがあるようなページがあるかというと、実はそこまでないんじゃないか、というのが最初に言っていたところです。確かにヘッダのお知らせ情報のような、部分的にはあるのだけれど、全体としてはそんなにないんじゃないかと思っている。

じゃあなんで分けていたんだっけ?という話になって、本来は分けない方が良いんですよね。チームでちゃんとサービスが作れて運営できればいいはずなので。どう分けたほうがいいかというのはサービス固有の話になって、そのときにビジネスドメインに合わせて分けようという話になるはずです。ところが、マイクロフロントエンドというようにフロントエンドといった瞬間に、技術的なレイヤで分けようとしようという気持ちになってしまい、そこで齟齬が出てしまうんじゃないというのが、今の気持ちですね。

qsona: ビジネスドメインと思っているのが、バックエンドからとフロントエンドからで見えているビジネスドメインが微妙に異なるというのは、Menuみたいな話でもあるのかなと思います。

teppeis: それで言うと、それをどういう組織で作って行くか?という話になるのですが、うちの場合はバックエンドとクライアントを同じチームが見ているので、そこの間に境界がない。一個のビジネスドメインとしてプロダクトを作っています。それはサービスや組織の文脈によって多分違う。自分のところはそういうふうに分けたので、もちろんポータルのようにいろんなものが混ざる特殊なページはあるのだけれど、結果的にマイクロフロントエンドのようなものはそんなにする必要がある部分がなかった、というのがこの前から今までの経緯です。

qsona: アンケートの中で、そもそも一つのページの中にいろんなドメインが混ざってしまうのをどうやって避けたらいいか、みたいなことを書いてくれた人がいました。今の議論は、そもそも混ざってしまうから、というところから出発しているんですが。

teppeis: それはやっぱりプロダクトマネージャーの仕事ですね。(会場笑)

qsona: デザインと情報設計的な観点ではどうなのですかね、僕はちょっと疎いのですが。会場の中にデザインに興味がある方もいると思いますので。… 一旦、半分くらい喋った気がするので、休憩を入れさせていただきます。


前半の総括

まず、三人のモチベーションがそれぞれ異なっている点がとても興味深いです。lacolacoさんの事例では、複数サービスでの共通化のためにUIコンポーネントのWeb Components化を進めていく過程で、バックエンドのサービスと密接に結びつくようなUIコンポーネントが存在するため、それの扱い方としてバックエンドとセットにしたいのが出発点とのことでした。また、teppeisさんは、lacolacoさんと同じく複数サービスに共通で同じコンポーネントを出すために、そのUIも含めたマイクロサービス・組織が必要になってくるというのが最初のモチベーションだったが、結果的に各プロダクトで共通のUIを出したいという要求自体が減っていったとのことでした。Quramyさんは、上の2人とは違い、CIが遅いのを改善したい/新しい技術の導入のハードルを下げたい など、技術的なモチベーションが高いとのことでした。

qsona個人的にも、いずれの立場にも非常に納得を感じました。FiNCはバックエンドを主に Ruby on Rails でのマイクロサービスで構築していますが、そのモチベーションは、将来的には組織やプロダクトの独立を見越しており、一方で現在実際に恩恵を受けているのは技術的な独立(CI・技術選定)も大きいと感じています。

その上で、前半では主にお互いのモチベーションを確認した上で、進めていった上で起き得る問題点などについて議論されました。モチベーションが異なる中でも、話していてだんだん議論が噛み合ってくる感じというか、大体同じゴールを目指しているような感覚があり、Micro Frontendsというモデルはそれなりに頑健なものなのだろうと感じています。

後編ではさらに、Micro Frontends間の連携手法やBFFとの関係などについて議論が進んでいきます。