BFF (Backend for Frontend) パターン with YARP
概要
BFF (Backend for Frontend) パターンは、特定のフロントエンドアプリケーション(Web、モバイルなど)のニーズに合わせてバックエンドサービスを構築するアーキテクチャパターンです。 .NETエコシステムにおいて、このBFFを実装するための強力なツールとして YARP (Yet Another Reverse Proxy) があります。
このドキュメントでは、YARPを使用したBFFパターンの基本概念と実装方法について解説します。
BFF パターンとは
マイクロサービスアーキテクチャにおいて、汎用的なバックエンドAPIをそのままフロントエンドから呼び出すと、以下のような問題が発生することがあります。
- 過剰なデータ取得 (Over-fetching): 画面表示に不要なデータまで取得してしまう。
- 不足データによる複数リクエスト (Under-fetching): 1つの画面を表示するために複数のAPIコールが必要になる。
- プロトコルの不一致: バックエンドがgRPCで、フロントエンドがRESTを期待している場合など。
BFFは、フロントエンドとバックエンドサービスの間に配置され、フロントエンド専用のAPIゲートウェイとして機能します。これにより、リクエストの集約、データの整形、認証・認可のハンドリングなどを行います。
YARP (Yet Another Reverse Proxy) とは
YARPは、Microsoftが開発したオープンソースのライブラリで、ASP.NET Core上に構築された高パフォーマンスなリバースプロキシツールキットです。
YARPの特徴
- ASP.NET Core ベース: ミドルウェアパイプライン、DI、構成システムなど、既存のASP.NET Coreの知識を活用できます。
- 高いカスタマイズ性: ルーティング、負荷分散、ヘルスチェック、リクエスト/レスポンスの変換(Transform)などをコードまたは設定ファイルで柔軟に定義できます。
- パフォーマンス: .NETの最新のパフォーマンス最適化の恩恵を受けています。
実装手順
1. パッケージのインストール
まず、BFFとなるASP.NET Coreプロジェクトを作成し、YARPのNuGetパッケージをインストールします。
dotnet add package Yarp.ReverseProxy
2. 設定ファイル (appsettings.json) の記述
YARPの動作は主に Routes (リクエストの振り分けルール) と Clusters (転送先のバックエンドサービス) で定義します。
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"ReverseProxy": {
"Routes": {
"products-route": {
"ClusterId": "products-cluster",
"Match": {
"Path": "/api/products/{**catch-all}"
},
"Transforms": [
{ "PathPattern": "{**catch-all}" }
]
},
"orders-route": {
"ClusterId": "orders-cluster",
"Match": {
"Path": "/api/orders/{**catch-all}"
}
}
},
"Clusters": {
"products-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:5001/"
}
}
},
"orders-cluster": {
"Destinations": {
"destination1": {
"Address": "https://localhost:5002/"
}
}
}
}
}
}
3. Program.cs の設定
YARPサービスをDIコンテナに登録し、ミドルウェアパイプラインに追加します。
var builder = WebApplication.CreateBuilder(args);
// YARPの設定を読み込む
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"));
var app = builder.Build();
// YARPのミドルウェアを有効化
app.MapReverseProxy();
app.Run();
高度な利用例:リクエスト/レスポンスの変換 (Transforms)
BFFの重要な役割の一つは、フロントエンドに合わせてデータを加工することです。YARPでは Transforms を使用してこれを行います。
設定ファイルでの変換
ヘッダーの追加やパスの書き換えなどは設定ファイルで完結できます。
"Transforms": [
{ "RequestHeader": "X-BFF-Client", "Set": "Web-App" },
{ "PathRemovePrefix": "/api" }
]
コードによるカスタム変換
より複雑なロジック(例:レスポンスボディの書き換えや集約)が必要な場合は、C#コードでTransformを定義できます。
builder.Services.AddReverseProxy()
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"))
.AddTransforms(builderContext =>
{
builderContext.AddRequestTransform(transformContext =>
{
// リクエストに対するカスタム処理
transformContext.ProxyRequest.Headers.Add("X-Custom-Header", "Value");
return ValueTask.CompletedTask;
});
});
BFFにおける認証・認可
YARPを使用するBFFでは、認証をBFF層で一元管理することが一般的です。
- Cookie認証: フロントエンドとBFF間はHttpOnly Cookieを使用してセッション管理を行います。
- トークン中継: BFFはCookieからユーザー情報を検証し、バックエンドサービスへのリクエストにはアクセストークン(JWTなど)を付与して転送します。
// トークン転送のTransform例
builderContext.AddRequestTransform(async transformContext =>
{
var accessToken = await transformContext.HttpContext.GetTokenAsync("access_token");
if (accessToken != null)
{
transformContext.ProxyRequest.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
}
});
メリットとデメリット
メリット
- フロントエンドの簡素化: 複雑なAPI呼び出しや認証ロジックを隠蔽できる。
- セキュリティ向上: トークンをブラウザに保存せず、BFFで管理することでXSS対策などが容易になる。
- 柔軟性: バックエンドの変更をBFFで吸収し、フロントエンドへの影響を最小限に抑えられる。
デメリット
- 単一障害点: BFFがダウンするとフロントエンド全体が機能しなくなる可能性がある。
- レイテンシ: プロキシを経由するため、わずかながらオーバーヘッドが発生する。
- 運用コスト: 管理・デプロイするコンポーネントが増える。
まとめ
YARPを使用することで、.NET環境において高機能かつパフォーマンスに優れたBFFを容易に構築できます。特にマイクロサービスアーキテクチャを採用している場合、フロントエンドごとの要件に柔軟に対応するための重要なレイヤーとなります。