バックエンド API 直接呼び出しの限界と BFF の存在理由
この章で学ぶこと
1
1 つの API を複数画面で共有したときに起きる問題
2
over-fetching と under-fetching の 2 つのトレードオフ
3
BFF パターンによる問題の解消
4
BFF がバックエンド API を集約・整形する仕組み
図解
アーキテクチャ全体像と BFF の位置
1章で示したブラウザ・BFF・バックエンド API の構成図(再掲)
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
コマンド
docker compose up
$ cd ch02-bff-basics$ docker compose up -d
ch02-bff-basicsこの章のサンプルコードのディレクトリ
docker compose up -dコンテナをバックグラウンドで起動
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
図解
起動する 3 つのコンテナ
docker compose up で起動する 3 つのコンテナ
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
図解
Web 版とモバイル版の表示情報
モバイル版と Web 版の商品詳細画面の情報量の違い
注記: ここから先の演習は「もし BFF がなかったら?」という仮定で進める(BFF コンテナは起動済みだが、しばらく使わない)
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
解説
バックエンド API が返すデータの性質
業務ドメインのデータをそのまま返す
商品サービスは商品に関する情報を、画面の都合とは無関係に、データ構造のまま返す
API そのものは悪くない
問題は「画面から直接呼ぶ」「用途の違う画面で 1 つの API を共有する」という使い方で起きる
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
図解
over-fetching と under-fetching
1 つの API を共有する 2 つのクライアントに起きるトレードオフ
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
図解
バックエンド APIを直接呼び出す構成
BFF なしでクライアントがバックエンド APIを直接叩く構成
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
実演
商品サービス API の実行
目的商品サービスの API レスポンスに不要なフィールドが含まれること(over-fetching)を確認する
実行する
コマンド$ curl http://localhost:3001/api/products/p-001
※ Windows(PowerShell)では curl を curl.exe に読み替えてください
確認する
ポイントレスポンスに 12 個のフィールドが含まれること / モバイルが使うのは name・price・images の 3 つだけであること
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
図解
モバイル版画面と over-fetching
モバイル版の商品詳細画面(再掲)と、レスポンス 12 フィールドのうち使うのは 3 つだけであることの対比
何が over か — 画面が使うのは name・price・images の 3 フィールドだけなのに、description、specs、stock、warehouseCode など残りの 9 フィールドも毎回受け取っている
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
実演
レビューサービス API の実行
目的Web 版の画面表示に 2 回のリクエストが必要であること(under-fetching)を確認する
実行する
コマンド$ curl http://localhost:3002/api/products/p-001/reviews
※ Windows(PowerShell)では curl を curl.exe に読み替えてください
確認する
ポイントレビュー情報は商品サービスとは別のリクエストで取得が必要であること / Web 版は画面 1 つに 2 回のリクエストが必要であること
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
図解
Web 版画面と under-fetching
Web 版の商品詳細画面(再掲)と、1 画面の表示に 2 回のリクエストが必要であることの対比
何が under か — 商品サービスへの 1 回のリクエストでは画面に必要なデータが揃わず、レビューサービスへの追加リクエストが必要になる
さらに変換処理も残る — 在庫数 142 を「在庫あり」へ、価格 15800 を「¥15,800」へ変換する処理をクライアント側で実装しなければならない
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
図解
BFF がバックエンド API を集約・整形する
BFF が 2 つのバックエンド APIを束ねて 1 つのレスポンスを返す構成
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
解説
BFF の定義
BFF(Backend for Frontend)
特定のフロントエンドに最適化したバックエンド層
役割
バックエンド APIのデータを集約・整形して、そのフロントエンドが必要とする形で提供する
クライアントごとに用意する
Web 用の BFF とモバイル用の BFF をそれぞれ置く
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
図解
BFF を含む 3 つのコンテナ
BFF・商品サービス・レビューサービスの 3 コンテナが起動した状態
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
実演
BFF エンドポイントの実行
目的BFF を通すと 1 回のリクエストで画面描画に必要なデータが揃うことを確認する
実行する
コマンド$ curl http://localhost:3000/web/products/p-001
※ Windows(PowerShell)では curl を curl.exe に読み替えてください
確認する
ポイント不要なフィールドが除外されていること / 価格が通貨形式、在庫が「在庫あり」に変換済みであること / 1 回のリクエストで商品情報とレビュー情報の両方が含まれること
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
図解
直接呼び出しと BFF 経由の比較
観点
バックエンド API 直接
BFF 経由
リクエスト回数
2 回
1 回
不要フィールド
9 個
なし
データ変換
クライアント側
BFF が実施済み
在庫表示
数値 142
「在庫あり」
価格表示
数値 15800
「¥15,800」
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
解説
BFF アプリケーションの構成
Express(Node.js)
この章の BFF は Express フレームワークで実装されている
エントリポイント: src/bff.js
Express アプリの起動と、ルートハンドラの登録を行うファイル
ルートハンドラ: src/routes/web-product.js
BFF の API 定義。バックエンド API の呼び出しとデータ変換の処理をまとめている
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
コード
BFF のルートハンドラ
BFF の API 定義
バックエンド API の呼び出しとデータ変換の処理を 1 つのルートハンドラにまとめている
ch02-bff-basics/src/routes/web-product.js
お手元のエディタでお開きください
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
解説
Promise.all による並行呼び出し
const [product, reviews] = await Promise.all([ fetch(`${PRODUCT_SERVICE}/api/products/${id}`).then((r) => r.json()), fetch(`${REVIEW_SERVICE}/api/products/${id}/reviews`).then((r) => r.json()),]);
Promise.all
2 つのバックエンド API を同時に呼び出し、両方の結果が揃うまで待つ
1 回のリクエストで完結
クライアントから見ると BFF への 1 回のリクエストで済む
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
解説
表示用データへの変換
表示用データ
BFF がバックエンド APIのデータを画面表示に必要な形に変換した結果のオブジェクト
不要フィールドの除外
必要なフィールドだけを取り出す
表示形式への変換
数値を通貨形式や「在庫あり」に変換する
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
解説
表示用データの変換例
price: `¥${product.price.toLocaleString()}`,stockStatus: product.stock > 0 ? "在庫あり" : "在庫なし",
toLocaleString()
数値を桁区切り付きの文字列に変換するメソッド
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ
まとめ
この章のまとめ
✓1 つのバックエンド API を複数のクライアントで共有すると over-fetching と under-fetching が発生する
✓BFF は特定のフロントエンドに最適化したバックエンド層である
✓BFF はバックエンド APIのデータを集約・整形して表示用データとして提供する
✓BFF により、クライアントは 1 回のリクエストで画面描画に必要なデータを取得できる
次章: API 集約とデータ変換
この章の位置づけ
環境起動
API直接呼び出しの問題
実演:API直接呼び出し
BFFパターン
実演:BFF
BFFのコード
まとめ