1
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?

APIクライアント自動生成の導入 - 手動fetchからの脱却 - Day 11

1
Last updated at Posted at 2026-05-12

はじめに

Day 10では、ファイル読み込みモジュールの設計とFileSearchクラスの実装について書きました。

今回はAPIクライアントの自動生成ツール導入について書きます。手動fetchの問題点と、swagger-typescript-apiへの切り替え経緯を記録します。


手動fetchの問題点

初期段階では、fetchを直接記述する方法でバックエンドとフロントエンドを連携していました。この方法には以下の問題がありました。

  • URLの打ち間違いやメソッドの取り違えが発生しやすい
  • ポート番号をコード内にハードコーディングする必要がある
  • バックエンドの修正やエンドポイントの追加のたびに手動で修正する必要があり、正確性に欠ける

エンドポイントが増加するにつれてこれらのリスクが高まると判断し、APIクライアントの自動生成ツールの導入を決めました。


swagger-typescript-apiを選んだ理由

FastAPIはSwagger形式のAPI定義(openapi.json)を自動生成します。swagger-typescript-apiはこのopenapi.jsonを入力として、TypeScriptの型付きAPIクライアントを自動生成するツールです。

FastAPIとTypeScriptの組み合わせに対して、追加の設定なしに型付きクライアントを生成できる点が採用の決め手でした。

生成されたApiクラスはtimer・goals・dataの3プロパティで構成されており、各エンドポイントがメソッドとして定義されます。timerプロパティの例は以下の通りです。

export class Api
  SecurityDataType extends unknown,
> extends HttpClient<SecurityDataType> {
  timer = {
    timerStartTimerStartGet: (params: RequestParams = {}) =>
      this.request<any, any>({
        path: `/timer/start`,
        method: "GET",
        format: "json",
        ...params,
      }),

    timerEndTimerStopPost: (params: RequestParams = {}) =>
      this.request<any, any>({
        path: `/timer/stop`,
        method: "POST",
        format: "json",
        ...params,
      }),

    todayTimerTimerTodayGet: (params: RequestParams = {}) =>
      this.request<any, any>({
        path: `/timer/today`,
        method: "GET",
        format: "json",
        ...params,
      }),
  };
  goals = { /* goalsSetGoalsSavePost / goalsUpdateGoalsUpdatePost */ };
  data = { /* getToJsonlDataJsonGet / getToCsvDataCsvGet */ };
}

goals・dataも同様の構造でメソッドが定義されています。エンドポイントの全一覧はDay 5で記載しています。


実行方法

APIクライアントの生成はpackage.jsonにスクリプトとして登録しています。

{
  "scripts": {
    "api-gen": "npx swagger-typescript-api generate --path http://localhost:8082/openapi.json --output ./src/api --name backend_api.ts"
  }
}

スクリプトはURLから直接openapi.jsonを取得する方式を採用しています。ブラウザでjsonを手動コピーする方法は手順が増えるうえにコピーミスのリスクがあるため廃止しました。動作しているサーバーから直接取得することで、動作確認の取れた状態のAPIを生成できます。

今後もエンドポイントの追加が確実であるため、1コマンドで更新できる状態にしておくことで開発の利便性を確保しています。


フロントエンドでの使用方法

生成したApiクラスは共通モジュールとしてインスタンス化し、各コンポーネントからimportして使用する設計にしています。

import { Api } from "../../api/backend_api";
export const api = new Api({baseUrl:'http://localhost:8082'});

この設計により、バックエンドの修正後にAPIクライアントを再生成しても既存の呼び出し箇所への影響を最小限に留めることができます。


おわりに

今日はAPIクライアント自動生成の導入について書きました。

手動fetchは小規模な段階では問題になりにくいですが、エンドポイントが増えるにつれてミスのリスクが積み重なります。NN機能・統計機能・ログ機能の実装が予定されていることを考えると、この段階で自動生成に切り替えておくことは合理的な判断だと考えています。

Day 12ではtimer画面の本実装について書く予定です。テーブル描画の実装過程と、非同期通信でハマったポイントを記録します。


この記事は連載「クラウドに依存しないマイルストーン管理ツール開発記」のDay 11です。

1
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
1
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?