03
第 3 章

API 集約とデータ変換

この章で学ぶこと
1 複数の下流サービスを 1 レスポンスにまとめる API 集約
2 Promise.all による並列呼び出しの仕組み
3 呼び出し順序を制御するオーケストレーション
4 ドメインモデルを View Model に変換するデータ変換と DTO
図解

BFF の集約・変換機能の位置

1章の全体像から API 集約とデータ変換の位置をハイライトした構成図

この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
コマンド

docker compose up

$ cd ch03-api-aggregation$ docker compose up -d
ch03-api-aggregationこの章のサンプルコードのディレクトリ
docker compose up -d5 つのコンテナをバックグラウンドで起動
この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
図解

起動する 5 つのコンテナ

docker compose up で起動する 5 つのコンテナ

この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
解説

API 集約とは

API 集約(Aggregation)
複数の下流サービスを呼び出し、結果を 1 つのレスポンスに統合する処理
フロントエンドのメリット
BFF への 1 回のリクエストで画面に必要なデータをまとめて取得できる
この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
図解

API 集約の流れ

BFF が 3 サービスを並列に呼び出して 1 レスポンスにまとめる流れ

この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
コード

ダッシュボード API の実装

BFF が 3 つの下流サービスを並列に呼び出して結果を 1 つにまとめるコード
src/routes/dashboard.js
router.get("/api/dashboard", async (req, res) => {  const [profile, orders, notifications] = await Promise.all([    fetch("http://profile-service:3001/users/me").then((r) => r.json()),    fetch("http://order-service:3002/orders?limit=5").then((r) => r.json()),    fetch("http://notification-service:3003/notifications").then((r) =>      r.json()    ),  ]);  res.json({ profile, orders, notifications });});
この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
解説

Promise.all と分割代入

const [profile, orders, notifications] = await Promise.all([...]);
Promise.all
配列内のすべての Promise の完了を待ち、結果を配列で返す
分割代入
配列の各要素を個別の変数に展開する構文
await
Promise の完了まで処理を一時停止する
この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
実演

ダッシュボード API の実演

目的3 つの下流サービスのデータが BFF によって 1 つのレスポンスに集約されることを確認する
実行する
コマンド
$ curl http://localhost:3000/api/dashboard
確認する
ポイント
profile・orders・notifications の 3 つが 1 レスポンスに含まれること
この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
解説

オーケストレーションとは

オーケストレーション
下流サービスの呼び出し順序と依存関係を BFF が制御すること
逐次呼び出し
前の呼び出しの結果が次に必要な場合、完了を待ってから次に進む
逐次と並列の組み合わせ
依存のある呼び出しは逐次、独立した呼び出しは並列で実行
この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
図解

オーケストレーションの流れ

逐次と並列を組み合わせた 2 ステップの呼び出しフロー

この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
コード

注文詳細 API の実装

逐次呼び出しと並列呼び出しを組み合わせたオーケストレーションの実装
src/routes/order-details.js
// ステップ 1: 注文を取得(後続が依存)const order = await fetch(  `http://order-service:3002/orders/${req.params.orderId}`).then((r) => r.json());// ステップ 2: 配送先と注文明細を並列に取得const [shipping, items] = await Promise.all([  fetch(`http://shipping-service:3004/addresses/${order.shippingAddressId}`)    .then((r) => r.json()),  fetch(`http://order-service:3002/orders/${req.params.orderId}/items`)    .then((r) => r.json()),]);
この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
実演

注文詳細 API の実演

目的逐次と並列を組み合わせたオーケストレーションが依存関係に従って正しくデータを集約することを確認する
実行する
コマンド
$ curl http://localhost:3000/api/order-details/ord-001
確認する
ポイント
order の shippingAddressId と shipping の id が一致すること / order・shipping・items の 3 つが 1 レスポンスに含まれること
この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
解説

データ変換とは

データ変換(Transformation)
下流サービスのデータ形式を UI が必要とする形式に変換する処理
ドメインモデル
下流サービスが内部処理に適した形式で返すデータ
View Model への変換
日付整形・通貨フォーマット・不要フィールド除去など、UI の都合に合わせる
この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
図解

ドメインモデルから View Model への変換

ドメインモデルと View Model の対比、変換関数がつなぐ構成

この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
解説

DTO とは

DTO(Data Transfer Object)
サービスの境界を越えてデータを運ぶための、値だけを持つデータ構造
ドメインモデルも DTO の一種
下流サービスからデータを受け取る入れ物
View Model も DTO の一種
UI の表示に特化した DTO
この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
コード

変換関数の実装

注文のドメインモデルを View Model に変換する mapper 関数
src/mappers/order.js
const STATUS_LABELS = {  shipped: "発送済み",  delivered: "配送完了",};function toOrderViewModel(order) {  return {    orderId: order.id,    orderDate: new Date(order.created_at).toLocaleDateString("ja-JP"),    totalAmount: `¥${order.total_amount.toLocaleString()}`,    status: STATUS_LABELS[order.status],  };}
この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
実演

データ変換の実演

目的下流 API のドメインモデルと BFF の View Model を比較して、データ変換の実物を確認する
実行する
コマンド
$ curl http://localhost:3002/orders/ord-001$ curl http://localhost:3000/api/orders/ord-001
確認する
ポイント
日付形式の変換 / 金額への通貨記号付与 / ステータスの和訳 / 不要フィールドの除去
この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ
まとめ

この章のまとめ

API 集約により、フロントエンドは BFF への 1 回のリクエストで複数サービスのデータを取得できる
並列呼び出しは Promise.all で複数のリクエストを同時に発行して待ち合わせる
オーケストレーションにより、依存関係のある呼び出しを逐次、独立した呼び出しを並列で制御できる
データ変換により、下流のドメインモデルを UI に適した View Model に変換できる
DTO はサービスの境界を越えてデータを運ぶための値だけを持つデータ構造である
次章: 認証境界としての BFF
この章の位置づけ
環境起動
API集約
オーケストレーション
データ変換
まとめ