React × FastAPI の疎通方法

## 1. 🔗 HTTP通信の基本構造

### クライアント側（フロントエンド）
```ts
fetch("http://localhost:8000/api/resource")
  .then((res) => res.json())
  .then((data) => setState(data));
```

### サーバー側（FastAPI例）
```python
@app.get("/api/resource")
def get_resource():
    return {"message": "成功"}
```

---

## 2. ✅ CORS (Cross-Origin Resource Sharing)

### 必要性
- ポート番号やドメインが異なる場合、ブラウザが **セキュリティ制限で通信をブロック**する
- これを緩和するため、バックエンドで CORS を設定

### FastAPIのCORS設定例
```python
from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:5173"],  # フロントエンドのURL
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
```

---

## 3. 🔐 API設計とエンドポイントの構成

### ベストプラクティス
| 種類           | HTTPメソッド | エンドポイントの例          |
|----------------|---------------|------------------------------|
| 一覧取得       | `GET`         | `/api/resources`             |
| 単体取得       | `GET`         | `/api/resources/{id}`        |
| 作成           | `POST`        | `/api/resources`             |
| 更新           | `PUT`/`PATCH` | `/api/resources/{id}`        |
| 削除           | `DELETE`      | `/api/resources/{id}`        |

---

## 4. 🛠️ バックエンドの設計ポイント

### ✅ Pydanticモデルでデータ整形
```python
class ResourceResponse(BaseModel):
    id: UUID
    title: str
    description: str

    class Config:
        orm_mode = True
```

### ✅ ORMとリレーション
```python
# モデル定義
class Resource(Base):
    __tablename__ = "resources"
    id = Column(UUID, primary_key=True)
    title = Column(String)
    user = relationship("User", back_populates="resources")
```

---

## 5. ⚠️ 注意すべきポイント（よくある落とし穴）

| 問題                             | 原因 |
|----------------------------------|------|
| CORSエラー                       | バックエンドにCORSミドルウェアがない/ドメインが不一致 |
| fetch() で 500エラー              | バックエンドで `AttributeError` など発生している |
| `undefined` が表示される         | レスポンスのプロパティ名が異なる or null データ |
| オブジェクトがそのまま表示される | `React` 側で `object` を直接描画している場合 |
| JSONの型不一致                   | PydanticレスポンスとDBの整合が取れていない |

---

## 6. 🧪 疎通確認チェックリスト

- [ ] バックエンド起動（例：`uvicorn`）
- [ ] フロントエンド起動（例：`vite`）
- [ ] `/api/resource` にブラウザからアクセスしてレスポンス確認
- [ ] DevTools の Network タブでステータスコードを確認（200が正解）
- [ ] CORSエラーが出ていないか確認
- [ ] `fetch()` でデータが取得できているか `console.log` で確認

---

## 7. 🚀 開発フロー（開発チーム向け）

1. バックエンド：新しいエンドポイント設計・作成
2. OpenAPI（Swagger UI）でレスポンス仕様を確認
3. フロントエンド：fetchやaxiosでエンドポイントを叩く
4. UIにデータをバインドして表示確認
5. デバッグ：CORS / レスポンス構造 / エラー発生箇所の確認

---

## 8. 🔒 セキュリティと命名に関する留意点

- 環境変数にURLやトークンなど**機密情報は絶対にハードコーディングしない**
- 公開用の変数名やIDにアプリの**内部情報や実名、UUIDの命名規則**が漏れないようにする
- APIレスポンスでは**最低限の情報だけ返す（userのemail等を不用意に返さない）**

---

## 9. ⚡ CORSエラーのよくある原因と実践的解決策

| 現象 | 原因 | 解決策 |
|--------|--------|------------|
| `No 'Access-Control-Allow-Origin'` | allow_originsにドメイン指定無 | 明示的にURLを指定 |
| `credentials flag is true but origin is *` | allow_credentials=True と * 不適合 | allow_originsは"*"を回避 |
| OPTIONS 405 | Preflightリクエストが拒否 | allow_methods=["*"] |
| 500 Internal Server Error | FastAPI側でコード上のバグ | ログを見よう |
| React側のfetchの方法が違う | credentials: 'include'が不適切 | backendと同期して設定 |

### fetch 側でも重要
```ts
fetch("http://localhost:8000/api/data", {
  method: "GET",
  credentials: "include"
});
```

---

## 10. 🧱 中間APIゲートウェイ(BFF)の基礎

### 考え方
BFF = Backend For Frontend

> フロント側に特化したAPIゲートウェイを用意して、ドメインを同一にする手段

### 構成イメージ
```
[ Frontend (React) ]
      ↓ fetch
[ BFF (FastAPI や Node.js) ]
      ↓ internal
[ REST / GraphQL APIs ]
```

### メリット
- ドメイン統一 (コンテナ編)
- アイデンティティ隔離
- 認証/キャッシュを同期に管理

---

## ✅ まとめ

| 観点          | 要点 |
|---------------|------|
| 通信手段      | `fetch` / `axios` → RESTful API |
| CORS対策      | `CORSMiddleware` 必須 |
| データ構造    | バックエンドは Pydantic、フロントは TypeScript で厳格に |
| 疎通確認      | DevTools + Swaggerで状態を確認 |
| 安全設計      | 適切なレスポンス定義と制限付き公開 |
| BFF           | ドメイン統一・集約・セキュア化に寄与 |

---

## ✅ おすすめ記事
- [ReactプロジェクトでのAPI調査のベストプラクティス]
- [FastAPI x SQLAlchemy x Alembic のチュートリアル]
- [BFF を搭載した構成解説記事]