BFFについて
BFF作ったこともなければ、こういうプロジェクトに入ったこともないがBFFにした方が良いのか?みたいな場面があったことを思い出したので、たまたま目に入ったこの機会に読んでみました。
BFF(Backend For Frontend)パターンとは何か?
BFFパターンは、特定のクライアントサイドアプリケーション向けの専用のバックエンドサービスを構築することに焦点を当てたソフトウェア設計パターン。
これは、複数のアプリケーションにサービスを提供する一般的なAPIを提供するのではなく、特定のフロントエンドアプリケーションの特定のニーズに合わせてバックエンドサービスを作成する特化したアプローチです。
言い換えれば、BFFパターンは、一つの一般的なバックエンドサービスに依存するのではなく、特定のクライアントサイドアプリケーションごとに専用のバックエンドサービスを作成することを含んでいます。
BFFパターンは、バックエンドサービスがより小さく、管理しやすいコンポーネントに分割され、独立して開発およびデプロイされるマイクロサービスアーキテクチャでよく使用されます。
BFFパターンを使用することで、ソフトウェア開発者は、パフォーマンスとスケーラビリティを最適化できる各フロントエンドアプリケーション向けの専用のバックエンドサービスを作成できます。
このアプローチは、バックエンドサービスの管理における柔軟性も提供します。各サービスは他のサービスから独立して更新および保守できます。
BFF(Backend For Frontend)パターンはどのように機能するのか?
BFFパターンは、特定のフロントエンドアプリケーションに特化した専用のバックエンドサービスを作成することを含みます。これらのバックエンドサービスは、フロントエンドアプリケーションが必要とするすべてのビジネスロジックとデータアクセスを処理します。また、データをフロントエンドアプリケーションに適した形式に変換する責任もあります。
フロントエンドアプリケーションは、明確に定義されたAPIを使用してバックエンドサービスと通信します。このAPIは、フロントエンドアプリケーションに特化して設計され、アプリケーションが必要とするすべてのデータと機能へのアクセスを提供します。
バックエンドサービスは、このAPIを実装し、必要な機能を提供する責任があります。
BFFパターンを実装するために、ソフトウェア開発者は通常、フロントエンドアプリケーションの特定のニーズを特定し始めます。
次に、パフォーマンスとスケーラビリティを最適化し、必要な機能を提供する専用のバックエンドサービスを作成します。このサービスは、明確に定義されたAPIを使用してフロントエンドアプリケーションと統合されます。
なんとなくのイメージでコードも書いてみました。
フロントからはこんな感じになりそう。
import React, { useEffect, useState } from 'react';
import axios from 'axios';
interface ResponseData {
data1: any;
data2: any;
data3: any;
}
const App: React.FC = () => {
const [data, setData] = useState<ResponseData | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
const response = await axios.get<ResponseData>('http://localhost:3000/client-request');
setData(response.data);
} catch (error) {
console.error(error);
}
};
fetchData();
}, []);
if (!data) {
return <div>Loading...</div>;
}
return (
<div>
<h1>Data from Microservice 1</h1>
<pre>{JSON.stringify(data.data1, null, 2)}</pre>
<h1>Data from Microservice 2</h1>
<pre>{JSON.stringify(data.data2, null, 2)}</pre>
<h1>Data from Microservice 3</h1>
<pre>{JSON.stringify(data.data3, null, 2)}</pre>
</div>
);
};
export default App;
BFFはこんな感じになりそう
const express = require('express');
const axios = require('axios');
const app = express();
const port = 3000;
app.get('/client-request', async (req, res) => {
try {
const [response1, response2, response3] = await Promise.all([
axios.get('http://microservice1/api-endpoint'),
axios.get('http://microservice2/api-endpoint'),
axios.get('http://microservice3/api-endpoint')
]);
const result = {
data1: response1.data,
data2: response2.data,
data3: response3.data
};
res.send(result);
} catch (error) {
console.error(error);
res.status(500).send('An error occurred while processing the request.');
}
});
app.listen(port, () => {
console.log(`BFF app listening at http://localhost:${port}`);
});
これは個人的な感覚ですが、「データをフロントエンドアプリケーションに適した形式に変換する責任もある」とあるように多分BFFの中身をいじるのはフロントの人が多い気がしているのでBFF実装はフロントの人が馴染みある言語で書いてあげるのが良さそうだなーと思いました。
BFF(Backend For Frontend)パターンの利点
BFFパターンは、ウェブアプリケーションの開発における多くの利点を提供します。以下に、その主な利点をいくつか挙げてみましょう。
パフォーマンスの最適化
BFFパターンを使用すると、ソフトウェア開発者は特定のフロントエンドアプリケーションのパフォーマンスを最適化するための専用のバックエンドサービスを作成できます。これにより、アプリケーションのパフォーマンスを向上させることができます。
スケーラビリティの向上
BFFパターンは、フロントエンドアプリケーションのスケーラビリティを向上させるのに役立ちます。各バックエンドサービスは独立してスケールアップまたはスケールダウンでき、アプリケーションの需要に応じてリソースを調整することができます。
保守性の向上
BFFパターンを使用すると、ソフトウェア開発者は各バックエンドサービスを独立して更新および保守することができます。これにより、アプリケーションの保守性が向上します。
開発の効率化
BFFパターンは、フロントエンドとバックエンドの開発を分離することを可能にします。これにより、開発者は特定のフロントエンドアプリケーションに特化したバックエンドサービスを作成し、開発プロセスを効率化することができます。
まとめ
メリットだらけじゃん!という感じではありますが、新たなコードベースとインフラが必要になるのでメンテナンスの負担だったりが発生し、システムの複雑度は上がります。
またBFF構築する際はスキルセットとしてフロントエンドとバックエンドの両方の知識を必要とします。
ということでとりあえずはBFFのイメージ湧いたので使える時に使ってみようかなと思いました。
この記事が気に入ったらサポートをしてみませんか?