2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ベテランさんが教えてくれない「BFF(Backend For Frontend)」を小学生でもわかるように解説

2
Last updated at Posted at 2026-06-19

概要

BFFって聞くけど、なんやねんって思う人いますよね💦
ベテランさんとかもなかなか教えてくれたりしないです。
前は「新人は使えない」「なんでこんなのも知らないの?」みたいな技術マウントを
取られることなどよくありました。そう言っている割に教えてくれなかったり、
やたら難しい用語で説明してきたりで、ちんぷんかんぷんでした。
なのでそうならないように小学生にもわかるレベルで、解説していきます。

今回はRails,Hono,Next.jsで実装してますが、
皆さんが使っている言語など置き換えて学んでくださいね!

AI時代だからこそ設計を学ぶ

コードを書く価値は無くなってきたので、設計を学ぶ意義は大きいと思います!
設計を語れる方が大事な時代だからです!

小学生にもわかる説明

「料理屋さん」で考えてみましょう!あなたが料理屋さんに入って席に座ったとします。
注文するとき、こんなことを考えませんよね!

「ドリンクは飲み物担当に、料理はシェフに、デザートはパティシエに…」

お客さんはホール係に「コース料理お願いします」と1回言うだけ。
あとはホール係が各担当に振り分けて、全部まとめてテーブルに届けてくれます。

これがBFF(backend for frontend)です。

ChatGPT Image 2026年6月19日 10_02_46.png

BFFがないと何が困るの?

あなたが料理屋さんに入って席に座りました。でも、この店にはホール係がいません。

例えばマッチングアプリのプロフィール画面を作るとしたら、注文するとき、こうなります。

「名前を聞きたいから名前厨房へ…いいね数を聞きたいからいいね厨房へ…マッチング数はマッチング厨房へ…」

ChatGPT Image 2026年6月19日 10_33_12.png

お客さん(Next.js)が自分で各厨房に4回取りに行かないといけないんです。

これの何が問題かというと、

  • 表示が遅い 4回取りに行くから、料理が揃うまで時間がかかる
  • コードが複雑 いろんな厨房に直接頼むので、Next.jsのコードが複雑になる
  • 修正が大変 厨房が増えるたびに、Next.jsも修正が必要になる

お客さんはただ「プロフィール画面を見たい」だけなのに、自分で各厨房を走り回らないといけない。

これはお客さんの仕事じゃないですよね。💦

✅ BFFがあると何が変わる?

ホール係(BFF)が間に入るだけで、さっきの問題が全部解決します。

お客さん(Next.js)はホール係(BFF)に1回言うだけ

あとはホール係が各厨房に取りに行って、全部まとめてテーブルに届けてくれます。

さっきの3つの問題がこう変わります。

問題 BFFあり
表示が遅い ✅ 1回のリクエストで済むので速い
コードが複雑 ✅ Next.jsはBFFを叩くだけでシンプル
修正が大変 ✅ 厨房が増えてもBFFだけ直せばOK

ホール係(BFF)がいるだけで、お客さん(Next.js)はラクになる。これがBFFの役割です。

全体のアーキテクチャ

実際のアプリではこういう構成になります。

┌─────────────────┐
│   Next.js        │  フロントエンド(画面)
│   port: 3000     │
└────────┬────────┘
         │ HTTP
┌────────▼────────┐
│   BFF            │  フロント専用API・データの取りまとめ
│   port: 4000     │
└────────┬────────┘
         │ HTTP
┌────────▼────────┐
│   Rails(API)   │  ビジネスロジック・DB操作
│   port: 8000     │
└────────┬────────┘
         │
┌────────▼────────┐
│   DB             │  PostgreSQL
└─────────────────┘

ポイントはそれぞれが隣しか知らないことです。

  • Next.jsはBFFしか知らない
  • BFFはRailsしか知らない
  • RailsはDBしか知らない

これがクリーンに保てる理由です。

ChatGPT Image 2026年6月19日 10_52_42.png

BFFに何を使う?

BFFを作るとき、何のフレームワークを使えばいいか迷いますよね。
よく候補に上がるのはこの3つです。

Rails NestJS Hono
言語 Ruby TypeScript TypeScript
Next.jsとの相性 △(言語が違う) ◎(同じTS・型共有) ◎(同じTS・型共有)
学習コスト 低い 高い 低い
速度 普通 普通 速い
向いてる場面 チームがRuby慣れ 大規模・マイクロサービス BFF・軽量API

RailsをBFFにするとどうなる?

動きますが、Next.jsと言語が違うのでフロントエンジニアがBFFを触りにくくなります。また責務の分離(コードの整理整頓) が崩れやすくなります。

新人エンジニアは知らないとやばい😱 「責務の分離」ってなーに?🤔( フロントエンドで解説)

NestJSをBFFにするとどうなる?

TypeScriptで書けますが、デコレーター・モジュール・DIなど覚えることが多く、
BFFだけに使うには過剰です。

HonoがBFFに向いている理由

BFFに必要なのは「リクエストを受けて・APIを叩いて・まとめて返す」だけです。
HonoはそれをTypeScriptで最もシンプルに書けます。

この記事ではHonoを使って実装します。

ディレクトリ構成

ここからはマッチングアプリのプロフィール画面を例に、実際のコードを見ていきます。アプリ全体のディレクトリ構成はこうなります。

matching-app/
├── frontend/          # Next.js(画面)
├── bff/               # Hono(BFF)
└── backend/           # Rails(APIサーバー)

それぞれが完全に分離しています。

  • frontend/ はBFFのURLしか知らない
  • bff/ はRailsのURLしか知らない
  • backend/ はDBしか知らない

次の章からそれぞれの実装を見ていきます。

1️⃣ Rails(APIサーバー)― 厨房

Railsは「厨房」 です。料理を作ることに集中します。
ホール係(BFF) が何人いるかも、お客さん(Next.js)が誰かも知りません。
ただ「作ってください」と言われたら作るだけです。

技術的に言うと、ビジネスロジックとDB操作に集中するので、
BFFのことは知りません。

backend/app/controllers/api/v1/users_controller.rb
module Api
  module V1
    class UsersController < ApplicationController
      def show
        user = User.find(params[:id])
        render json: {
          id:         user.id,
          nickname:   user.nickname,
          age:        user.age,
          prefecture: user.prefecture,
          bio:        user.bio,
          thumbnail:  user.thumbnail_url
        }
      end
    end
  end
end
backend/app/controllers/api/v1/likes_controller.rb
module Api
  module V1
    class LikesController < ApplicationController
      def count
        count = Like.where(to_user_id: params[:user_id]).count
        render json: { count: count }
      end
    end
  end
end
backend/app/controllers/api/v1/messages_controller.rb
module Api
  module V1
    class MessagesController < ApplicationController
      def unread_count
        count = Message.where(to_user_id: params[:user_id], read: false).count
        render json: { count: count }
      end
    end
  end
end

2️⃣ Hono(BFF)― ホール係

Honoは「ホール係」 です。お客さん(Next.js)から注文を受けて、
各厨房(Rails)に取りに行き、まとめて返します。

技術的に言うと、複数のAPIをまとめてNext.jsが必要な形に整形して返します。
Railsしか知りません。

bff/src/index.ts
import { Hono } from "hono";

const app = new Hono();
const RAILS_API = process.env.RAILS_API_URL;

// プロフィール画面用API
// Next.jsはここを1回叩くだけでOK
app.get("/bff/profiles/:userId", async (c) => {
  const userId = c.req.param("userId");

  // Railsの複数APIを並列で叩く
  const [userRes, likeRes, messageRes] = await Promise.all([
    fetch(`${RAILS_API}/api/v1/users/${userId}`),
    fetch(`${RAILS_API}/api/v1/likes/count?user_id=${userId}`),
    fetch(`${RAILS_API}/api/v1/messages/unread_count?user_id=${userId}`),
  ]);

  const [user, likes, messages] = await Promise.all([
    userRes.json(),
    likeRes.json(),
    messageRes.json(),
  ]);

  // Next.jsが必要な形にまとめて返す
  return c.json({
    user: {
      id:         user.id,
      nickname:   user.nickname,
      age:        user.age,
      prefecture: user.prefecture,
      bio:        user.bio,
      thumbnail:  user.thumbnail,
    },
    stats: {
      like_count:           likes.count,
      unread_message_count: messages.count,
    },
  });
});

ChatGPT Image 2026年6月19日 12_22_48.png

3️⃣ Next.js(フロント)― お客さん

Next.jsは「お客さん」です。ホール係(BFF)に注文するだけです。

技術的に言うと、BFFしか知りません。Railsの存在を知らなくていいです。

// frontend/app/profile/[userId]/page.tsx
type ProfileData = {
  user: {
    id: number;
    nickname: string;
    age: number;
    prefecture: string;
    bio: string;
    thumbnail: string;
  };
  stats: {
    like_count: number;
    unread_message_count: number;
  };
};

async function getProfile(userId: string): Promise<ProfileData> {
  // BFFを1回叩くだけ!
  const res = await fetch(
    `${process.env.BFF_URL}/bff/profiles/${userId}`
  );
  return res.json();
}

export default async function ProfilePage({
  params,
}: {
  params: { userId: string };
}) {
  const { user, stats } = await getProfile(params.userId);

  return (
    <div>
      <img src={user.thumbnail} alt={user.nickname} />
      <h1>{user.nickname}{user.age}{user.prefecture}</h1>
      <p>{user.bio}</p>
      <p>もらったいいね{stats.like_count}</p>
      <p>未読メッセージ{stats.unread_message_count}</p>
    </div>
  );
}

BFFが太りすぎるとどうなる?

BFFは「まとめて返すだけ」が役割です。
ここにビジネスロジック(アプリのルール。「自分にはいいねできない」「マッチングしていない相手にはメッセージ送れない」など)を書き始めると、「どこに何が書いてあるかわからない」状態になります。

料理屋さんで言うと、ホール係が厨房に入って料理まで作り始めるイメージです。それはシェフ(Rails)の仕事ですよね。

// ❌ これはNG:BFFにビジネスロジックを書く
app.post("/bff/likes", async (c) => {
  const body = await c.req.json();

  // ビジネスルールをBFFに書いてはいけない
  if (body.from_user_id === body.to_user_id) {
    return c.json({ error: "自分にはいいねできません" }, 400);
  }
});

// ✅ これがOK:BFFはRailsに流すだけ
app.post("/bff/likes", async (c) => {
  const body = await c.req.json();
  const res = await fetch(`${RAILS_API}/api/v1/likes`, {
    method: "POST",
    body:   JSON.stringify(body),
  });
  return c.json(await res.json(), res.status);
});

BFFのルール

  • ✅ 複数APIのレスポンスをまとめる
  • ✅ フロントが必要な形に整形する
  • ❌ ビジネスロジックは書かない
  • ❌ DBに直接アクセスしない

ChatGPT Image 2026年6月19日 12_45_40.png

採用すべきでないケース

BFFは万能ではありません。状況によっては採用しない方がいいケースがあります。

🔰 APIが1〜2本しかない場合

まとめる必要がないので、BFFを挟むだけ無駄です。Next.jsから直接Railsを叩けばシンプルに保てます。

🔰 小規模・MVPで速度優先の場合

サービスの方向性が決まっていない段階でBFFを作ると、仕様変更のたびに修正箇所が増えます。まずは動くものを作ることを優先しましょう。

🔰 チームがRubyエンジニアだけの場合

TypeScriptのHonoを追加するより、RailsにBFF的な処理をまとめた方がチーム全体で管理しやすいです。

💡 例えば、金融機関の開発では、セキュリティ要件やチーム構成によってBFFをバックエンドに集約するケースもあります。BFFを採用すべきかどうかは、チームの規模・技術スタック・ドメインの複雑さで判断しましょう。

🎯 まとめ

今回はBFFについて解説しました。

役割 技術 やること
画面 Next.js BFFを叩くだけ
BFF Hono 複数APIをまとめて返す
APIサーバー Rails ビジネスロジック・DB操作
DB PostgreSQL データの保存

BFFの2つのルール

  • ✅ 複数APIのレスポンスをまとめてフロントが必要な形に返す
  • ❌ ビジネスロジックは書かない・DBに直接アクセスしない

BFFを採用すべきでないケース

  • APIが1〜2本しかない
  • 小規模・MVPで速度優先
  • チームの技術スタックに合わない

BFFは「フロントエンドのためのまとめ係」です。

料理屋さんのホール係と同じで、お客さん(Next.js)が快適に注文できるように、裏側の複雑さを隠してくれる存在です。

設計に迷ったときは「これはホール係の仕事か?厨房の仕事か?」と考えてみてください。

使用したAI

  • Claude
  • ChatGPT
2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?