FastAPIは、Pythonの型ヒントとPydanticによるデータ検証、OpenAPIスキーマの生成を利用できるWeb APIフレームワークです。
ReactやVueなどのフロントエンドと組み合わせるときは、フレームワーク同士を接続する方法よりも、APIの契約、認証、配信単位、障害時の扱いを先に決める必要があります。
この記事では、FastAPIとフロントエンドの境界で起きやすい不整合を減らすために、設計から運用までの判断基準を順に整理します。
最初に決める五つの設計項目
実装に入る前に、次の五項目を決めておくと、バックエンドとフロントエンドが別々の前提で進む事態を避けやすくなります。
| 設計項目 | 決める内容 | 曖昧な場合に起きること |
|---|---|---|
| 配置 | 同じリポジトリや同じ配信元に置くか、別々に運用するか | ビルドと公開の責任範囲が混ざる |
| API契約 | URL、入力、出力、エラー、互換性の方針 | 項目変更の影響をフロントエンドが検知できない |
| 認証 | ログイン方式、トークンやCookieの扱い、権限 | CORS、CSRF、XSSへの対策がかみ合わない |
| 通信 | HTTPリクエストで足りるか、WebSocketが必要か | 必要以上に複雑な接続管理を抱える |
| 運用 | テスト、ログ、デプロイ、切り戻しの単位 | 片側の更新でサービス全体が止まる |
プロジェクト構成は責任範囲で分ける
バックエンドとフロントエンドをディレクトリで分ける目的は、見た目を整えることではありません。
依存関係、テスト、ビルド、公開の責任範囲を明確にするためです。
project-root/
├── backend/
│ ├── app/
│ │ ├── main.py
│ │ ├── routers/
│ │ ├── models/
│ │ ├── schemas/
│ │ └── dependencies/
│ ├── tests/
│ ├── Dockerfile
│ └── requirements.txt
├── frontend/
│ ├── src/
│ ├── public/
│ ├── tests/
│ ├── Dockerfile
│ └── package.json
└── docker-compose.yml
backend/には、APIのルート、データモデル、入出力スキーマ、認証などを置きます。frontend/には、画面、状態管理、APIクライアント、表示側のテストを置きます。docker-compose.ymlには、開発や結合確認で一緒に動かすサービスの関係を記述します。
この構成は一例です。
小さなAPIをどの段階で分割するかは、FastAPIのプロジェクト構成を段階的に整理する方法も参考になります。
OpenAPIをAPI契約の基準にする
API契約とは、フロントエンドとバックエンドの間で合意するURL、HTTPメソッド、入力、出力、エラーの形式です。
FastAPIでは、Pydanticモデルやルート定義からOpenAPIスキーマを生成できるため、そのスキーマを両者の共通資料として扱えます。
OpenAPIからTypeScriptの型やAPIクライアントを生成すると、項目名や必須項目の食い違いを開発中に見つけやすくなります。
ただし、生成された型はブラウザが受信した値を実行時に検証する仕組みではありません。
バックエンドの入力と出力の検証、フロントエンドの例外処理、両者を通した結合テストは別に必要です。
契約に含めたい内容
- 成功時のレスポンスだけでなく、入力エラー、認証エラー、対象なし、サーバーエラーの形式
- 日時、列挙値、空文字、
null、省略可能な項目の扱い - ページネーション、並び順、検索条件の表現
- 既存フロントエンドを壊す変更と、互換性を保てる変更の区別
たとえば、レスポンスの項目を必須に変更すると、古いデータや段階的なリリースで不整合が起こる可能性があります。
スキーマの差分確認と結合テストをCIに入れ、変更がどちら側へ影響するかをレビューできる状態にします。
RESTとWebSocketを用途で分ける
一覧取得、登録、更新、削除のように一回の要求へ一回応答する処理は、HTTPによるAPIが理解しやすい構成です。
ブラウザ標準のfetchやHTTPクライアントからJSONを送受信し、処理結果をHTTPステータスと統一したエラー本文で返します。
WebSocketは、接続を維持したままサーバーとブラウザが双方向にデータを送れる通信方式です。
チャットや即時通知のように、サーバー側から継続的に更新を届ける必要がある場合に候補になります。
| 条件 | 向く方式 | 確認事項 |
|---|---|---|
| 要求ごとに結果を返す | HTTP API | タイムアウト、再試行、重複送信への対応 |
| サーバーから随時通知する | WebSocketを検討 | 再接続、認証の更新、切断時の扱い |
| 更新頻度が低い | HTTP APIによる定期取得も比較 | 通信量と実装の複雑さ |
リアルタイムという言葉だけでWebSocketを選ぶと、再接続や接続状態の管理が増えます。
画面が許容できる更新間隔と、サーバーから送る必要がある情報を先に整理します。
認証とブラウザの安全対策を分けて考える
認証は利用者が誰かを確認する処理で、認可は確認した利用者に操作を許可するかを決める処理です。
JWT、OAuth2、Bearerトークンは認証設計で使われる要素ですが、いずれかを採用するだけで安全性が決まるわけではありません。
JWTは署名付きのトークン形式であり、内容を暗号化する仕組みとは限りません。
有効期限、失効、権限、保存場所、更新方法まで含め、アプリケーションの要件に合わせて設計します。
CORSは認証機能ではない
CORSは、ブラウザ上のフロントエンドが異なるオリジンのAPIを呼び出せるかを制御する仕組みです。
オリジンは、プロトコル、ドメイン、ポートの組み合わせで決まります。
フロントエンドとAPIを別オリジンで運用する場合は、CORSMiddlewareで許可するオリジン、メソッド、ヘッダー、資格情報の扱いを明示します。
資格情報を使う構成で広いワイルドカード許可に頼らず、本番環境のフロントエンドを具体的に指定します。
CSRFとXSSは条件が異なる
Cookieをブラウザが自動送信する認証では、意図しないサイトから操作を送られるCSRFへの対策を設計します。
一方、ページへ不正なスクリプトを混入させるXSSは、トークンの保存方式にかかわらず、画面へ出す値の扱いとセキュリティヘッダーを含めて対策します。
- 外部通信はHTTPSで保護し、リバースプロキシで終端する場合は信頼する転送元も限定する
- 入力モデルと出力モデルを分け、不要な内部項目をレスポンスへ含めない
- エラー本文の形式を統一し、内部の例外や秘密情報をそのまま返さない
- 認証、認可、CORS、CSRF、XSSを一つの設定項目として扱わない
フロントエンドの配信方法を選ぶ
フロントエンドの成果物は、FastAPIとは別に配信する方法と、FastAPIから静的ファイルとして配信する方法があります。
どちらが適切かは、サービスの規模だけではなく、公開頻度、キャッシュ、担当範囲、障害の切り分けで決まります。
| 構成 | 扱いやすい場面 | 注意点 |
|---|---|---|
| 別々に配信 | 画面とAPIを独立して更新したい | CORS、環境別のAPI URL、公開順序を管理する |
| FastAPIから配信 | 一つの成果物として運用したい | ビルド成果物の配置、キャッシュ、画面側ルーティングを確認する |
FastAPIのStaticFilesを使う最小構成は次のとおりです。
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI()
app.mount(
'/assets',
StaticFiles(directory='frontend/dist/assets'),
name='assets',
)
これは静的ファイルを配信する出発点であり、SPAの画面URLへ直接アクセスしたときのフォールバックまでは定義していません。
成果物のディレクトリ名と画面側ルーティングはビルドツールによって異なるため、実際の出力を確認して設定します。
DockerとCI/CDは再現性と検証に使う
バックエンドとフロントエンドに別々のDockerfileを用意すると、それぞれの依存関係とビルド工程を分離できます。
Composeは両者とデータベースなどをまとめて起動し、開発環境や結合確認を再現する用途に向きます。
Dockerfile、Compose、Python依存ファイルの役割は、PythonアプリのDocker構成で詳しく確認できます。
CI/CDで確認する順序
- バックエンドの単体テストと入出力スキーマの検証を行う
- フロントエンドの型検査、テスト、ビルドを行う
- 生成したOpenAPIスキーマの差分を確認する
- フロントエンドからAPIを呼ぶ結合テストを行う
- コンテナを作成し、起動確認後に環境ごとの手順で公開する
パイプラインを用意する目的は、単に公開操作を自動化することではありません。
API契約の変更を含め、同じ検証を更新のたびに再現できる状態を作ることです。
ReactとVueはチームと要件で選ぶ
FastAPIはHTTPやWebSocketを通じてフロントエンドと通信するため、ReactとVueのどちらかに限定されません。
選定では、流行や抽象的な規模感よりも、既存資産、チームの経験、必要な周辺ライブラリ、画面の配信方式、長期保守の担当者を比較します。
- 既存プロジェクトと同じ技術を使うことで、部品や運用手順を再利用できるか
- チームがコンポーネント設計、状態管理、テストを継続できるか
- サーバー側レンダリングや静的生成など、必要な配信方式を構成できるか
- 認証、フォーム、アクセシビリティを含む画面要件を満たせるか
技術ごとの役割や選定基準は、Vue.jsとReactの違いと向いている開発ケースでも整理しています。
実装前の確認リスト
- APIの入力、出力、エラー形式をOpenAPIで共有できる
- 破壊的な変更を検知するテストとレビュー手順がある
- 認証と認可の責任範囲、有効期限、失効方法が決まっている
- CORSの許可範囲を環境ごとに限定している
- Cookie認証を使う場合のCSRF対策と、画面側のXSS対策を確認している
- HTTP APIとWebSocketの選定理由を説明できる
- フロントエンドの配信方法と画面側ルーティングを確認している
- 結合テストと切り戻しの手順がある
FastAPIとフロントエンドの連携を安定させるには、ライブラリの組み合わせより、両者の境界を契約として管理することが有効です。
型、エラー、認証、配信、運用の担当範囲を決め、変更をテストで検知できる構成へ整えます。
この記事に関連する株式会社greedenの取り組み
フロントエンドとAPIの境界を曖昧にしたまま進めると、変更のたびに認証や型の不整合が表面化します。
株式会社greedenは、要件整理からAPI、画面、テスト、運用まで一気通貫でWebシステム開発を支援します。
