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

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

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

本記事について

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

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

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

そもそもBFFとは何か

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

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

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

なぜBFFが必要なのか

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

「共通API」で誰も幸せにならない

従来は「1つの汎用APIを全クライアントで共有するのが普通でしたが、Web・モバイル・TVではそれぞれ画面サイズ・必要データ・認証要件が全く違うため、共通APIでは誰も幸せにならない、という問題がありました。BFFはこの問題を「クライアントごとに最適なAPIを提供する中間層」で解決します。

クライアント毎に責任を分離するのがBFFの思想です。

BFFが生まれた背景

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

従来: 1つの汎用APIを全クライアントで共有
[Web] ──┐
[Mobile]─→ [単一API] ──→ [Backend]
[TV]  ──┘

この構造の問題は、「Web用の変更がMobile側に影響する」「各クライアントが使わないフィールドまで取得している」「クライアント毎の認証要件が混在する」という3点です。Webとモバイルでは通信料の制約も違うため、1API共有は現実的ではない、と認識されるようになりBFFが生まれました。

BFFの典型的な責務

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

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

特にAPIアグリゲーションが重要で、画面1つを表示するために「ユーザー情報・注文履歴・レコメンド・広告」を別々に叩く必要がある場合、BFFが裏で「並列呼び出し」して1レスポンスに束ねられます。ブラウザが5回リクエストする必要がなくなり、体感速度が劇的に改善します。

BFFの典型構成

最も一般的な構成は、Next.jsなどのフルスタックFWを BFF層として使うパターンです。フロントと同じリポジトリに置くことで、UI開発とAPI整形を「同じチームで扱え」ます。

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

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

なぜBFFが有効か

BFFを挟むことで得られる具体的な効果は、大きく3つに整理できます。これらは単純にAPIを直接叩く構成では得られないものです。

① セキュリティの向上

ブラウザから直接外部APIを叩くと、APIキーや認証トークンがブラウザ側に露出します。BFF経由にすれば、トークンはサーバ側にだけ保持でき、ブラウザにはhttpOnly Cookieだけを渡せます。XSS(Cross-Site Scripting、スクリプト注入攻撃)でトークンが盗まれるリスクを根本的に排除できます。

② パフォーマンスの向上

複数のマイクロサービスを呼ぶ処理をBFF側で並列化」し、1つのレスポンスにまとめて返せます。ブラウザ↔BFF は同一オリジンで高速、BFF↔バックエンドは内部ネットワークで高速、という「二重の最適化」が効きます。

③ フロントエンド開発効率

フロントチームがAPIの形を「自分で決められる」ため、画面に必要なデータだけを綺麗に整形できます。バックエンドチームに「このフィールド追加して」と依頼する往復がなくなります。

BFFの実装パターン

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

BFFの実装手段は多岐にわたります。フレームワーク組込み型が簡単で、tRPCのような型安全型が尖った選択肢として人気です。

パターン備考
Next.js API Routes / Server ActionsReact系で最も普及
Nuxt Server RoutesVue系で同等の選択肢
Remix Loader/ActionWeb標準重視の設計思想
tRPCTypeScript型共有で神業級の開発体験
Hono + Cloudflare WorkersエッジBFF・低遅延
専用 Express/Fastify軽量・FEと独立リポジトリ

Next.js Server Components と Server Actions の登場により、BFFを別に作る」必要が減り、BFFはフレームワーク組込が主流になりつつあります。シンプルな用途なら Next.js だけで完結できます。

tRPCによる型安全BFF

tRPC は、TypeScriptの型をサーバとクライアントで完全共有する仕組みで、近年急速に普及しました。RESTGraphQL のようなスキーマ定義なしで、関数呼び出しのようにAPIを書けます。

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

// クライアント側 — サーバの型が自動で効く
const user = await trpc.user.byId.query("u_1")
// user の型は自動推論・入力はZodでバリデーション

利点スキーマファイル不要・型でエディタ補完・実行時バリデーション(Zod(TypeScript用スキーマ定義ライブラリ)との統合)。TypeScriptフルスタック(同一プロジェクト内にFE/BEが同居)の場合、圧倒的な開発効率を発揮します。

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

BFF vs GraphQL

BFFと似た問題を解く技術としてGraphQLもあり、どちらを選ぶかは迷いがちです。両者は「排他的ではなく」、組み合わせることもできますが、得意分野が異なるため使い分けが重要です。

観点BFFGraphQL
実装画面毎にエンドポイント単一エンドポイント
学習コスト軽い重い(設計・運用が難しい)
柔軟性サーバ側で固定形に整形クライアントが自由にクエリ
キャッシュHTTP標準で簡単別途設計が必要

BFFが合うケース」:クライアントがWeb/モバイルなど少数で、画面設計が安定している場合。GraphQLが合うケース」:多様なクライアント(モバイル・TV・外部パートナー)が自由にクエリしたい場合。

単一クライアント中心ならBFF、多様なクライアントが自由にクエリしたい時はGraphQL が定石です。

セッション管理の定石

BFFを使う場合の認証は、「ブラウザにはCookieだけ、BFFの裏で実トークンを管理」という定石があります。この構成が、XSS耐性とトークン管理の両方を最大化します。

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

この構成の決定的な利点は、ブラウザにJWTを一切露出させないこと。XSSでSession Cookieが盗まれる可能性はhttpOnly化で排除でき、万が一盗まれてもサーバ側で即時失効できます。JWTをブラウザに持たせる設計と比較して、セキュリティが一段上のレベルに到達します。

BFF + httpOnly Cookie が現代のWeb認証の最も安全な構成です。

BFFのアンチパターン

BFFは便利な反面、適切に薄く保たないと急速に肥大化して、新たな負債になります。典型的な失敗パターンを押さえておかないと、BFFそのものがもう一つのモノリスになります。

  • 肥大化:業務ロジックがBFFに流れ込み、中核サービスと二重化する。修正時に両方変える羽目に
  • サイロ化:各BFFが独自にユーザー管理やキャッシュを始め、一貫性が失われる
  • キャッシュの置き場所問題BFF内・バックエンド内・CDNのどこで何秒キャッシュするかが混乱する
  • 認証の多重化:各BFFが独立に認証実装を持ち、認証バグが各所で発生する

BFFフロント用の薄い層。業務ロジックを持ち込むと中核サービスと二重化して破綻します。

「BFFが本体になった日」(業界事例)

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

「Next.jsでサクッと書いちゃおう」という発想が半年後に恐ろしい規模の逆転を生んでいた、という光景はいろいろな現場で目撃されています。この事故の怖いところは、個々のPRレベルでは”ちょっと書くだけ”で済んでいたこと。1行の割引計算が、1ヶ月後には在庫引当に、半年後にはポイント計算に、1年後には「中核ロジックの大半」になっていた、というのが典型パターンです。

BFF「入口では無害に見えるが、放置すると必ず肥大化」する。「玄関ロビーに金庫を置くな」という教訓は、こうした事故の積み重ねから生まれています。

BFF薄く保つが鉄則。業務ロジックが入り込む兆候を早期に叩きます。

BFF導入の段階別判定表

BFFは入れる・入れないの判断が最も重要で、規模と構成から自動的に決まります。以下が実務での段階表です。

フェーズ規模・構成BFFの扱い実装方式
個人・MVP〜1,000 MAU不要(直接API叩き)fetch + useState
初期スタートアップ〜10,000 MAU・単一バックエンド薄いBFF(FW組込)Next.js API Routes / Server Actions
中規模SaaS10,000〜100,000 MAU・複数マイクロサービス統合BFFtRPC + Next.js
大規模100,000 MAU〜・多チーム専用BFF層(画面ごと)専用Express/Fastify + gRPC
マルチクライアントWeb + Mobile + TVクライアントごとBFF各クライアント専用
エッジ配信優先グローバル・低遅延重視Edge BFFHono + Cloudflare Workers

BFFを入れる実質下限はマイクロサービス化 + 3サービス以上の集約が必要」の時です。それ未満では Next.js API Routes / Server Actions の薄い層で十分で、専用BFFサーバを立てるのは過剰設計です。

BFF必要になってから「将来のために」で先取りすると運用コストで逆戻りします。

やってはいけないこと

BFF運用で事故る典型を整理します。どれもBFFが本体化する肥大化の入口になります。

禁じ手なぜダメか
BFFに業務ロジックを書く1年で中核サービスと二重化。玄関ロビーに金庫を置くな
BFFをバックエンドチームが所有画面変更のたびに他チーム調整。フロントチーム所有が鉄則
BFFとFEを別リポジトリに分離画面変更で2つのPRが必要、同期タイミングで事故
BFFにキャッシュ戦略なしオリジンへの負荷が集中、BFFがボトルネックに
BFFで認証を再実装(各BFFが独立)認証バグが各所で発生。統一認証に寄せる
REST + 手書き型でBFFとFEを繋ぐ型が分断、型定義の二重管理。tRPCで完全共有
BFFのタイムアウト未設定バックエンド障害でBFFごと倒れる雪崩連鎖
BFFで楽観ロックなしの更新同時更新でロストアップデート、データ破損
BFFをフロント以外のクライアントからも叩かせるBFFの意味が消える。用途特化を保つ
マイクロフロントエンドでBFFを1つに統合チーム独立性が失われる。各フロントにBFF
「小規模でもBFFを入れた方がモダン」と先取り過剰設計。Server Actionsで十分な規模に専用BFFは運用負荷だけ増える
「BFFとGraphQLは同じ」と混同哲学が逆。クライアント少数ならBFF、多クライアント自由クエリならGraphQL

「2024年時点の定番はNext.js Server Actions + tRPCServer Componentsで取得、Server Actionsで更新、tRPCで型共有。この3点セットでBFFという別層」を意識せず実装できます。伝統的な別サーバBFFは、マイクロサービスが5本以上・多チーム並列開発になる時だけ検討します。

BFF玄関ロビー。業務ロジックを持ち込んだ瞬間に二つ目のモノリスになります。

AI判断軸

AI時代に有利AI時代に不利
tRPC(型完全共有)手書きREST + 型定義の二重管理
Next.js Server Actions(ファイル内で完結)別リポジトリのBFF・分散した仕様
Zodスキーマでバリデーションstring検証の手書き
同一リポジトリでFE/BE同居リポジトリ分離・仕様が遠い
  1. 規模から必要性を判断(小規模は不要、マイクロサービスで必須)
  2. フレームワーク組込を優先(Next.js API Routes / Server Actions)
  3. 型共有 + 同一リポジトリtRPC + Zodが最強)
  4. BFFは薄く保つ(業務ロジックは中核サービスに残す)

tRPC + Zodの組み合わせがAI生成精度を最大化する

tRPCはフロントエンドとバックエンドの型を自動共有する仕組みで、Zodスキーマでバリデーションを定義すると、APIの入力・出力の型がフロント側にも自動で伝播します。AIにとっては「使えるAPIの一覧と各パラメータの型」がコードベース内に明示されているため、APIコールの生成精度が格段に上がります。

手書きのREST API + 型定義の二重管理では、フロント側の型とサーバ側の実装がずれた場合にAIがどちらを信じるべきか判断できず、不正確なコードを生成するリスクがあります。

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

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

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

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

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

この記事に関連する記事

まとめ

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

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

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

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

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

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