🌟

マイクロフロントエンドが我々にもたらすうまみとつらみ

2023/01/26に公開

はじめに

株式会社マクアケでエンジニアをしている @tokutoku3 です。

僕が携わっているMakuakeという応援購入サービスを支える管理画面では、1年半ほど前からマイクロフロントエンドというアーキテクチャを取り入れた開発・運用にトライしています。

本記事では、その経験を通して感じたことを紹介できればと思います。

対象読者

  • マイクロフロントエンドに興味がある
  • 試してみたいが、どんな観点があるかわからない
  • 他サービスでの事例を参考にしたい

書いていること

  • マイクロフロントエンドアーキテクチャを導入したサービス開発で実際に試していることや、感じているメリット/デメリットの話

書いていないこと

  • 具体的な実装サンプル
    • 実装に踏み込んだ話は別記事にしようと思っています

マイクロフロントエンドとは?

概念自体初見の方は、以下の記事を読むと雰囲気が掴めるでしょう。
https://micro-frontends.org/

ざっくり表現すると、マイクロサービスというアーキテクチャで得られるメリットやその考え方を、フロントエンドの領域にも展開することでより良いサービス開発につなげようという考え方です。

複数の小さなフロントエンドアプリケーションを束ねて、ユーザーからみた時に1つのアプリケーションとして振る舞わせるようなイメージですね。

オライリーからマイクロフロントエンドという書籍が少し前に発行されていますので、より詳細を知りたい方にはオススメです。

実際にサービスで試していること

Makuakeではプロジェクトを実施する人を実行者と呼ぶのですが、
その実行者向けの管理画面を、1年半ほど前からマイクロフロントエンドアーキテクチャに置き換えた開発を行っています。

置き換えにあたりいくつかの案を検討していたのですが、最終的に以下のような背景を解消する取り組みとして、試験的にマイクロフロントエンドを採用してみようという方針になりました。

  • 開発組織の人員が増え始め、モノリスなコードベースを並行して開発運用する際のコンフリクト解消や調整コストが高くなっていった
  • 使用している言語やライブラリのバージョンアップデートのたびに大規模なQAや一斉対応が必要になっており、ハードルが高い状態が続いていた
  • 「みんなが触るアプリケーション」であるが故に、個々人がサービスに対するオーナーシップを育みづらい環境になっていた
  • バックエンド領域のサービス分離は社内でもすでに事例があったが、フロントエンドは巨大なモノリスをメンテナンスし続けている状態だった

一口にマイクロフロントエンドアーキテクチャと言ってもいくつかの実現方法があるのですが、今回お話する管理画面では以下のようなアプローチを採用しています。

クライアントサイドコンポジション

今回マイクロフロントエンドを採用したサービスはログインが必要な管理画面だったため、SEOに関する考慮をする必要がありませんでした。
そのため、ブラウザ側で必要な各フロントエンドアプリケーションをロードし、必要なタイミングで結合して動作させる構成にしています。

サービスの特性によってはエッジサイドコンポジション()、サーバーサイドコンポジション()などの構成をとった方が良い可能性もありますが、現状はインフラやアーキテクチャ全体の構成が比較的小さくまとまるクライアントサイドコンポジションを試しています。

フロントエンドの配信環境にコンテナやサーバーを用意する必要がなく、AWS S3やGCP Storageのようなストレージサービスだけで完結するので、インフラのメンテナンスコストが非常に低い点が気に入っています。

デザインシステムをはじめとした共用概念の構築

ビジネスドメインを支えるチームごとに、小さなフロントエンドアプリケーションを開発できるようになるのがマイクロフロントエンドアーキテクチャです。

最終的に1つのアプリケーションとして動作することを考えると、一定の領域においては統制を取る必要があると考えており、その中の代表的な仕組みとしてデザインシステムを構築しました。

画面のデザインコンセプト、UIコンポーネントごとのガイドラインを定め、それに準拠したUIライブラリを実装・Storybookで確認できる環境をつくることで、各チームの画面デザイン・実装コストを下げ、管理画面全体のトンマナが大きくブレないようにする狙いを持っています。

垂直分割をメインにした部分的な水平分割

開発していたメンバー間ではそれぞれ「コンポーネント型マイクロフロントエンド」「ページ型マイクロフロントエンド」と表現していたのですが、オライリーのマイクロフロントエンド本の表現を参考にすると、以下のような分類になります。

  • 水平分割
    • 1つの画面に複数の小さなフロントエンドアプリケーションがまとまっている
  • 垂直分割
    • ページ(ビジネスドメイン)ごとにフロントエンドアプリケーションが分かれている

今回開発している管理画面では、共通メニュー領域とそれ以外のページ部分、という区分けのみ水平分割を行っており、ページ部分の領域をビジネスドメインごとに区切った垂直分割方式で実装しています。

完全な垂直分割方式を採用した場合は共通メニュー部分を各フロントエンドアプリケーション側で実装、または共通化したコンポーネントを読み込むような形になるのですが、以下のような理由で現在の構成に落ち着いています。

  • 段階的にマイクロフロントエンドアーキテクチャへ置き換えていく計画を立てていたため、共通部分を1つのチームで一元管理、1度のデプロイで切り替えられるようにしたかった
  • 旧画面ではVue2、新画面ではVue3、のように採用している技術スタックのバージョンが異なる時期が発生する見込みがあったので、画面側のアーキテクチャに合わせたそれぞれのナビゲーション実装を必要としない構成にしたかった

コンテキスト境界の設計

前述した垂直分割を実践するにあたり、業務ドメインを整理し境界が引けるポイントを探すという取り組みも進めています。

開発当初、チームとしては軽量DDDを取り入れている程度の経験値しかなかったのですが、本管理画面の開発を通して、ドメインエキスパートを巻き込んだドメインモデルの整理に取り組みました。

文化として馴染むまで時間はかかったのですが、今では職種を問わずサービスへの理解値が高まっていること、業務フローをチーム全体で理解しディスカッションできていることを踏まえると、実践して損はなかったと感じています。

結果として現状3つほど、それぞれのコンテキストを担う垂直分割型のフロントエンドアプリケーションができており、旧実装部分も順次設計・置き換えを行っていく予定です。

結局どうなの

大小さまざまな知見が得られたのですが、その中のいくつかを紹介します。

うまみ

チームで触るコードベースのスコープを小さくできた

シンプルですが、やはりパワフルで最大のうまみだと思います。
マイクロサービスと同様のメリットを享受しよう、というアーキテクチャなので、同じような嬉しさがあるなと改めて感じました。

  • 影響調査やシステム理解度の要求をチームが持っている各アプリケーションに閉じ込めることができた
  • デプロイをチームごとに分担でき、機能ごとのデプロイ速度も爆速になった
  • 特定のアプリケーション(画面)のみ、先行してバージョンアップや構成変更の検証ができるようになった
  • アプリケーション毎のオーナーが明確になり、開発運用にオーナーシップを持ってもらいやすくなった

コードを置き換えた範囲では前述した課題を解消し始められており、非常に良い走りだしができているので、今後もそれぞれのチームがサービスの価値を高めることに集中できる環境づくりを目指していきたいと思います。

画面の情報設計を意識する機会ができた

これはマイクロフロントエンドアーキテクチャそのものではなく、採用するにあたって副次的に得られたうまみではあるのですが、垂直分割型の設計を採用する場合は少なからず通る道だと思うので並べて書きました。

業務フローを理解し、誰がどのタイミングで、どんな情報に触れる必要があるのかという点は、みんなが気にしているようで意外と突き詰められていないものだなという感覚を持ちました。

開発当初フロントエンド分割のためにドメインを整理し、元々の画面にさまざまな業務ドメインが折り重なっていたことに気づいた際に「そりゃあコンフリクトも起きまくるよね」と白目になったのはいい思い出です。

つらみ

ブラウザがロードする通信量が増加していく

フロントエンドアプリケーションを分割した数だけ読みこむことになるため、モノリスなフロントエンドアプリケーションと比較してどうしても通信量が増えてしまうという課題があります。

今回のような管理画面では幾分要求が緩いケースもありますが、パブリックアクセスが可能なサービスにおいてはパフォーマンスの観点で致命的な問題になり得ます。

いくつかの対応策は検討や実践まで進んでいるものの、これについてはもう少し工夫が必要だと感じました。

  • CDN、ブラウザキャッシュを最大限活用する
  • Tree Shakingで可能な限りビルドファイルのサイズを削減する
  • アクセス時に全てのフロントエンドアプリケーションをロードするのではなく、必要なタイミングで必要な分をロードする

各フロントエンドアプリケーション間の通信やライフサイクルの統制が必要

理想は各フロントエンドアプリケーションが完全に独立することですが、水平分割な構成においてはどうしてもアプリケーション連携が必要なケースが発生するでしょう。

例えば以下のようなニーズが発生した場合、それを制御するための仕組みが必要です。

  • ログインしているかどうかで各水平分割アプリケーションの表示を切り替えたい
  • 水平分割アプリケーションAの描画が完了した後に水平分割アプリケーションBを表示したい

今回の管理画面実装では、マイクロフロントエンド全体で活用するカスタムイベントを定義し、必要なタイミングでpublishとsubscribeを行うことで値の受け渡しや順序の整合性を保つアプローチをとりました。

直近の課題は解決できたものの、各フロントエンドアプリケーション開発者が理解する必要のある独自ルールをどのようにわかりやすく整理していくかは今後も改善を重ねたいと思います。

筆者のスタンス

うまみもつらみも踏まえた上での感想は
「どのようなサービスでも採用すべきアーキテクチャでは(まだ)ない」 でした。

マイクロサービスアーキテクチャも同様ですが、サービスのフェーズ、開発組織の規模、抱えている課題感によってはマッチしない部分が多くなるケースも確実に存在すると感じました。

ただ、今回トライしている管理画面のように、課題と解決できる点が噛み合う領域では一考の価値がある選択肢ですし、今後噛み合う領域が増えていくことを楽しみにしたいアーキテクチャです。

マイクロフロントエンドを採用するサービスが増え、業界全体で知見や新しい発見がより積み重なっていくことに期待しつつ、僕もその流れをつくる一端として発信していけたら最高だなと思っています。

さいごに

この記事はMakuake Advent Calendar 2022の20日目の記事にする予定でしたが、なんやかんやありこのタイミングとなりました。
(今年はコンスタントに書きたい)

マクアケではマイクロフロントエンドをはじめとしたさまざまな技術を取り入れながら、世の中に生まれるアタラシイを支えるサービス開発に取り組んでいます。

そういった開発に興味がある方、もっとカジュアルに話してみたい方がいれば、ぜひ!

Discussion