フロントエンドアーキテクチャ

BFF設計 ― Backend For Frontendを薄く保つ ― 生成AI時代のアーキテクチャ超入門

BFF設計 ― Backend For Frontendを薄く保つ ― 生成AI時代のアーキテクチャ超入門

本記事について

当サイトを閲覧いただきありがとうございます。 本記事はシリーズ『生成AI時代のアーキテクチャ超入門』の「フロントエンドアーキテクチャ」カテゴリ第6弾として、BFFについて解説する記事です。

「共通APIで誰も幸せにならない」問題への解答として生まれた設計パターンです。本記事ではBFFの背景・典型責務・実装パターン(Next.js API Routes/tRPC/Hono)・GraphQLとの違い・アンチパターンまで解説し、「薄く保つ・必要になってから導入する」という運用の鉄則を示します。

本記事のテーマについてさらに詳しく知りたい方は『システム設計のセオリーと実践方法がこれ1冊でしっかりわかる教科書』・『安全なWebアプリケーションの作り方 第2版』も参考にしてみてください。

この記事の結論

  • BFFは薄く保つ(ビジネスロジックを入れない)
  • 規模から必要性を判断する(小規模ならServer Actionsで十分)
  • フロントチームが所有し、FEと同一リポジトリに置く
  • 型共有(tRPC+Zod)でAIの生産性を上げる

この記事を読む前に

本記事はブラウザ側(画面側)の仕組みの話が中心です。IT用語にあまり馴染みがない方は、基礎編の「Webサービスが動く仕組み」と「プログラムとAPIの基本」を先に読んでおくと格段に分かりやすくなると思います。また、読んでいて分からない用語が出てきたときは用語集で調べながら読み進められます。

そもそもBFFとは何か

BFFとは、ざっくり言えば「クライアントごとに最適なAPIを用意する中間層」です。

ホテルのコンシェルジュを想像してください。ビジネス客には会議室とタクシーの手配を、観光客には地図とレストランの予約を、それぞれ必要な情報だけを最適な形で渡します。全員に同じ分厚いガイドブック(汎用API)を渡しても、ほとんどのページは不要です。BFFはこのコンシェルジュ役で、Web・モバイル・TVなどクライアントごとに必要なデータだけを整形して返します。

共通API vs BFF(クライアント別API)の比較

なぜBFFが必要なのか

もしBFFがなかったらどうなるか。1つの汎用APIで全クライアントを賄うことになりますが、Web・モバイル・TVは画面サイズ・通信帯域・必要データ・認証要件が全く異なります。結果、全員に同じレスポンスを返すことで、誰にとっても最適でないAPIが生まれます。フロントが不要なデータを捨て、足りないデータを追加リクエストで補う非効率が積み重なり、パフォーマンスとセキュリティの両方が劣化します。

BFFパターンはSoundCloudのエンジニアが提唱し、Netflix・Spotify等で採用されて広まりました。マイクロサービス化が進んだ結果、フロントエンドが数十の異なるAPIを叩く必要が出てきたことが背景です。

BFFの典型的な責務

BFF「フロントの下請けをする薄いサーバ」が理想です。業務ロジックはバックエンドサービスに残し、BFFは表示・整形・プロキシに徹します。

責務内容
APIアグリゲーション複数のマイクロサービスから集めて1画面分にまとめる
データ整形画面に合わせた形式に変換・不要フィールド削除
認証・セッショントークン管理・Cookie化・秘密鍵の隠蔽
キャッシュAPIレスポンスのHTTP / エッジキャッシュ
レート制限DDoS対策・API悪用防止

効果は3つです。第一にセキュリティ──トークンをサーバ側にだけ保持し、ブラウザにはhttpOnly Cookieだけを渡せるため、XSSでトークンが盗まれるリスクを根本的に排除できます。第二にパフォーマンス──画面1つに必要な「ユーザー情報・注文履歴・レコメンド」BFFが裏で並列呼び出しして1レスポンスに束ねられます。第三に開発効率──フロントチームがAPIの形を自分で決められ、バックエンドへの「このフィールド追加して」の往復がなくなります。

[Browser]
   ↓ (same-origin通信・Cookie)
[Next.js API Routes / Server Actions]  ← BFF層
   ↓ (mTLS / 内部ネットワーク)
[Microservices / 外部API]

BFFの所有者はフロントエンドチームで、フロントと同じリポジトリに置くのが鉄板です。画面の変更に合わせてBFFも変わるため、同居していれば「画面を変えたらBFFも同時にPR」で完結します。

実装パターン ― フレームワーク組込が主流

BFF実装パターンの使い分け

実装の第一候補はNext.js API Routes / Server Actions(Vue系ならNuxt Server Routes)です。Server ComponentsとServer Actionsの登場によりBFFを別に作る」必要が減り、フレームワーク組込が主流になりました。エッジ低遅延重視ならHono+Cloudflare Workersマイクロサービスが多く多チーム並列開発になったら専用Express / Fastifyを検討します。

TypeScriptフルスタックならtRPCが強力です。スキーマファイル不要でサーバとクライアントの型を完全共有し、関数呼び出しのようにAPIを書けます。

// サーバ側
const appRouter = router({
  user: {
    byId: procedure.input(z.string()).query(({ input }) => ...)
  }
})

// クライアント側 — サーバの型が自動で効く
const user = await trpc.user.byId.query("u_1")

Next.js+tRPC+Zodが現代の型安全フルスタックの定番構成です。

なお似た問題を解くGraphQLとの使い分けは、クライアントがWeb / モバイルなど少数で画面設計が安定しているなら学習コストの軽いBFF、多様なクライアント(TV・外部パートナー)が自由にクエリしたいならGraphQL、が定石です。哲学が逆なので混同しないことが重要です。

セッション管理の定石

BFFを使う場合の認証は、「ブラウザにはCookieだけ、BFFの裏で実トークンを管理」という定石があります。

1. ブラウザ → IdP(Auth0等)でIDトークン取得
2. BFFにIDトークン送信
3. BFFが検証し、httpOnly Session Cookie発行
4. 以降のAPI呼び出しはCookieベース(ブラウザはJWTを一切触らない)
5. BFFが裏でAccess Token / Refresh Tokenを管理

ブラウザにJWTを一切露出させないため、XSS耐性が一段上のレベルになり、万が一Cookieが盗まれてもサーバ側で即時失効できます。BFF+httpOnly Cookieが現代のWeb認証の最も安全な構成です。

どう選べばいいのか ― 段階別判定表

BFF「入れる・入れない」の判断が最も重要で、規模と構成から自動的に決まります。

フェーズ規模・構成BFFの扱い
個人・MVP〜1,000 MAU不要(直接API叩き)
初期スタートアップ単一バックエンド薄いBFF(Next.js Server Actions)
中規模SaaS複数マイクロサービス統合BFF(tRPC+Next.js)
大規模・マルチクライアント多チーム / Web+Mobile+TV専用BFF層(クライアントごと)

BFFを専用サーバとして立てる実質下限はマイクロサービス化+3サービス以上の集約が必要」な時です。それ未満ではフレームワーク組込の薄い層で十分で、「将来のために」先取りすると運用コストで逆戻りします。

3つのシナリオで考える

個人開発・スタートアップの場合

この規模では、BFFはそもそも不要だと思います。フロントから直接APIを叩くか、Next.jsのServer Actionsを薄い層として使えば十分事足りてしまいます。専用のBFFサーバを「将来のために」と先取りしても、運用コストだけが増える結果になりがちです。

個人・スタートアップ ― 1か月で出せる構成が正解 ― 生成AI時代のアーキテクチャ超入門senkohome.com/arch-intro-case-startup/

中小SaaSの場合

複数のバックエンドサービスが生まれてきたら、tRPCとNext.jsによる統合BFFで型共有しながら集約するのが良いでしょう。フロントとバックエンドの間で型が自動的に揃うため、API仕様のズレによるバグをビルド時に検出できるようになるのが大きな利点です。

中小SaaS ― マネージドに寄せて少人数で回す ― 生成AI時代のアーキテクチャ超入門senkohome.com/arch-intro-case-saas/

大企業の場合

WebにMobile、TVまで揃うマルチクライアント・多チーム体制になって、初めてクライアントごとの専用BFF層が正当化されると考えています。チームごとにBFFのオーナーシップを持たせて、バックエンドのマイクロサービス群とはAPI契約(OpenAPIやGraphQL Schema)で疎結合にしておく形です。

大企業基幹系 ― 新しい技術より組織で成立する設計 ― 生成AI時代のアーキテクチャ超入門senkohome.com/arch-intro-case-enterprise/

AI判断軸 ― 型共有がAI生成精度を最大化する

tRPC+Zodの組み合わせ

tRPCはフロントとバックエンドの型を自動共有し、Zodスキーマでバリデーションを定義すると入力・出力の型がフロント側にも自動で伝播します。AIにとっては「使えるAPIの一覧と各パラメータの型」がコードベース内に明示されているため、APIコールの生成精度が格段に上がります。手書きのREST+型定義の二重管理では、フロントの型とサーバの実装がずれた場合にAIがどちらを信じるべきか判断できません。

Server ActionsでBFF層が不要になるケース

Next.js 14以降のServer Actionsを使えば、フォーム送信やデータ変更の処理をサーバサイドの関数として直接呼べます。薄いBFF層を別途用意する必要がなく、フロントのファイル内でサーバ処理が完結します。AIにとっても同一ファイル内にフロントとサーバの処理が共存するため、コンテキストの把握が容易です。

やってはいけないこと

BFFが本体化する肥大化の入口を、特に危険な6つに絞ります。

禁じ手なぜダメか → どうするか
BFFに業務ロジックを書く1年で中核サービスと二重化する → 割引計算・在庫引当はバックエンドに残す
BFFをバックエンドチームが所有画面変更のたびに他チーム調整が要る → フロントチーム所有にする
BFFとFEを別リポジトリに分離画面変更で2つのPRが必要になる → 同一リポジトリに同居させる
BFFで認証を再実装(各BFFが独立)認証バグが各所で発生する → 統一認証基盤に寄せる
BFFのタイムアウト未設定バックエンド障害でBFFごと倒れる → 全外部呼び出しに設定する
「小規模でもBFFがモダン」と先取り運用負荷だけ増える過剰設計 → Server Actionsで十分な規模では入れない

筆者メモ ― 「BFFが本体になった日」

「バックエンドチームの対応が遅いから」という理由で、Next.js API Routes側に割引計算や在庫引当のロジックを書き溜めた結果、1年後にはBFFが実質的な本体・本物のBackendはCRUDの置き場、という逆転構造になった現場の話が、いろいろな勉強会で共有されています。修正時は両方を直す必要があり、二重メンテで疲弊する顛末です。

この事故の怖いところは、個々のPRレベルでは「ちょっと書くだけ」で済んでいたことです。1行の割引計算が、半年後にはポイント計算に、1年後には中核ロジックの大半になっていた。BFFは入口では無害に見えますが、放置すると必ず肥大化します。「玄関ロビーに金庫を置くな」という教訓は、こうした事故の積み重ねから生まれています。

決めるべきこと — 自分のプロジェクトでの答えは?

以下の項目について、自分のプロジェクトの答えを1〜2文で言語化してみてください。曖昧なまま着手すると、必ず後から「なぜそう決めたんだっけ」が問われます。

  • BFFを設けるか(規模と構成から判断)
  • 実装技術(Next.js / tRPC / Hono / 専用サーバ)
  • リポジトリ構成(FEと同居 / 別リポジトリ)
  • 認証の扱い(Cookie / Bearer / Session)
  • キャッシュ戦略BFF内 / CDN / どちら優先か)

この記事に関連する記事

まとめ

本記事はBFFについて、責務・実装パターン・GraphQLとの違い・アンチパターン・型共有まで含めて解説しました。如何だったでしょうか。

BFFは薄く保ち、規模から必要性を判断し、型共有+同一リポジトリでAI生産性を最大化する。これが2026年のBFF設計の現実解です。

次回は認証認可(フロント側)(Cookie/JWT保管・XSS/CSRF対策)について解説します。

シリーズ目次に戻る → 『生成AI時代のアーキテクチャ超入門』の歩き方

本記事で扱った内容の詳細は Vercel 公式サイト も合わせて参考にしてください。

それでは次の記事も閲覧いただけると幸いです。