マイクロサービスアーキテクチャにおけるAPIコールの仕方とHTMLレンダリング

先日、マイクロサービスの呼び出し方として、[オーケストレーションとコレオグラフィについて書きました](http://qiita.com/kawasima/items/17475a993e03f249a077)が、同じく4章では、どうHTMLを組み立てるかという問題が提起されています。

![](https://www.oreilly.co.jp/books/images/picture978-4-87311-760-7.gif)

ここもやや難解なので、咀嚼を試みます。

## 課題設定

次のようなECサイトを考えることにします。そして、4つのマイクロサービスを合成して構成します。

- 商品カタログサービス
- ショッピングカートサービス
- ショップサービス
- リコメンドサービス

![ec1.png](https://qiita-image-store.s3.amazonaws.com/0/8475/d5fd9159-dd01-384d-e0c6-b8a04decdd4b.png)


## API合成

無垢な気持ちで設計すると、各々のマイクロサービスがWeb APIのインタフェースをもち、XMLやJSONを返して、ECサイト側で、テンプレートエンジンなどを用いて、HTMLをレンダリングするという方式になるかと思います。

そして、この形式でマイクロサービスを利用するサイト(アプリケーション)が増えていくと次の図のようになります。

![ec2.png](https://qiita-image-store.s3.amazonaws.com/0/8475/a524faa8-9a16-089f-bbb9-3c4e681ab562.png)

これには、次の3つの欠点があるとされています。

### [欠点1] APIレスポンスに無駄なものが含まれる

PC向けとモバイル向けのWebページでは、情報量や表示単位が異なることがよくあります。モバイル向けに必要のないたくさん項目までレスポンスに含まれるのは、通信料が跳ね上がることにも繋がり、重いサイトのレッテルを貼られることになりかねません。

### [欠点2] APIレスポンスの変更時にUIに影響ないかの確認が必要

例えば、商品名が当初30文字までだったところ、長い商品も出てきたので最大100文字に広げたい場合、商品カタログサービスのチームは単独でデータベース定義を変更するだけでは仕事は終わりになりません。

商品名が長くなることによって、表示崩れが発生しないか各利用サイトに確認して回らなくてはいけません。

というように、コンシューマ側がいかにAPIの内容変更に対して、強い作りをしていても、UIがからむと、どうしても疎にならない事態が発生しえます。

### [欠点3] APIの通信回数が多い

4つのサービスをAPI呼び出しするので、少なくとも4回のWeb APIコールが必要になります。これも欠点1と同じく、モバイルの通信料や画面描画の遅延にも繋がるので、解消したい課題になります。

## UI部品合成

欠点2の課題に対応するためには、HTMLレンダリングの責務をマイクロサービス側に持っていくという方式が考えられます。それがUI部品合成です。

![ec3.png](https://qiita-image-store.s3.amazonaws.com/0/8475/ed1f968d-c7a3-330e-85d9-971b853dbdc2.png)

サイト毎に異なるトンマナは、CSSを駆使してなんとかします。逆に言うとそういう、表示に関するレギュレーションをマイクロサービスのチーム側に持ってこれない組織は、この方式はとれないことになります。

また、この方式はモバイルネイティブアプリでは使えないというところも課題になります。
その他、他のマイクロサービスの結果をもって、別のサービスを呼び出したいということが、ままあるかと思いますが、その場合はやはり素直には使えません。次のBFFと併用することになります。

## APIゲートウェイとBFF

欠点3に対応するには、複数のマイクロサービス呼び出しを合成するAPIゲートウェイをアプリケーションとマイクロサービスの間に置き、アプリケーションからのAPI呼び出しを1回にすることです。

一般的なAPIゲートウェイは、そのレイヤでレスポンス内容を編集できるので、欠点1のデバイスごとや呼び出しアプリケーションごとにレスポンスをカスタマイズすることが可能になります。


![ec4.png](https://qiita-image-store.s3.amazonaws.com/0/8475/3f7ff7e6-12e4-7802-927a-08f930206f8e.png)

しかし、これはAPIゲートウェイがファットになることを意味し、そのメンテナンスが大変になります。

このAPIゲートウェイを、呼び出しデバイスおよびアプリケーションごとに分離し、その管理責任を呼び出し側アプリケーションのチームに渡すのが、Backends for Frontends (BFF)です。

![ec5.png](https://qiita-image-store.s3.amazonaws.com/0/8475/fe2e2813-c838-f165-5e18-18cdbcc3de0a.png)

マイクロサービスアーキテクチャ著者のSam Newmanは、このBFF推しです。

## BFFとアプリケーションの通信

ここから先は『マイクロサービスアーキテクチャ』本には出てこない話です。
一般的にはBFFはアプリケーションごとのAPIゲートウェイなので、HTMLのレンダリングはマイクロサービス側がUI部品合成に対応していない限り、BFFからはXMLやJSONをレスポンスし、各サイト(アプリケーション)ではそれを元にテンプレートにハメることになります。

そうするとサイト側の作りは、

1. まずレイアウトだけのHTMLを描画し、
2. XMLHttpRequestでBFFと通信して必要なデータを取ってきて、
3. コンテンツの再描画をおこなう

という処理フローになります。こうなると、SEO用のクローラーが正しくデータを解釈できなかったり、ユーザエクスペリエンスとしても、一瞬白い画面が出てしまう、応答性の悪いサイトと思われてしまう恐れがあります。

そこで初回表示は、サーバサイド、すなわちここではBFF側でやってしまおうというのがIsomorphicな考え方です。

koichik先生の[Isomorphic Survival Guide](https://speakerdeck.com/koichik/isomorphic-survival-guide)より引用させていただきます。

![Isomorphic Survival Guide P45](https://speakerd.s3.amazonaws.com/presentations/00b67327c8004e86b617b22d4e752180/slide_44.jpg)

この[Isomorphic Survival Guide](https://speakerdeck.com/koichik/isomorphic-survival-guide)では、Server - Client, Frontend - Backend のごっちゃに使われそうな用語を、分かりやすく定義してありますので、フロントエンドの開発する人は必読かと思います。

このIsomorphic Survival Guideを読むと、BFFという用語は「Server for Frontends」と呼びたくはなってきます。

## まとめ

書籍の中では触れられていませんでしたが、BFF化を進めていくと、そこで初回レンダリングをやりたくなってきます。BFFのIsomorphic対応は、これからマイクロサービスアーキテクチャ界隈で語られていくのではないかと思います。