💨

モノレポでAPI定義書からモデルを自動生成したらめっちゃ楽になった

に公開

TL;DR

  • モノレポに OpenAPI を置き、コードジェネレーションで Python と TypeScript の型を自動生成
  • スキーマを SSOT(Single Source of Truth)化することでドキュメント腐敗を防止
  • モデル生成はmakefileを使って、ワンコマンドで実行できるようにする

はじめまして!株式会社ハイクリでWebエンジニアをしているHamudoraです。

弊社で開発している時系列モデルを利用したアパレルの在庫管理システムでは、モデルの実装とデプロイ・Web UIの更新を効率化するためにもモノレポを採用しています。

最近、バージョン管理の煩雑さを解消したり、プロジェクトビルドを統一かしたりするなどの目的で、特に少人数のチームのプロダクトではモノレポ構成でプロダクトを開発しているチームが増えてきていると思います。

今回は、Webシステムのうちバックエンドの部分、APIスキーマの定義と実装の同期をどうとるか?ということについて考えていきましょう!

モデルを共通化すると好都合

今回、モノレポの利点を最大限意識して、APIの新規開発や保守をどのようにしていくか、ということについて考えてみましょう。

基本的に、RedocやSwaggerなどのAPI定義からテスト用のUIを自動生成できるサービスを使っているプロジェクトが多いと思います。それらのAPI定義は、OpenAPI仕様で記載されたスキーマに従って生成することが一般的です。

今回はこのAPI仕様書を使って、それ自身からモデルを自動生成することによって、モデルの構造をAPI仕様書に依存させる構造とします。

これによって、いわゆるAPI仕様書の更新漏れや、ドキュメントの腐敗などを防げることが期待されます。

さらに、モノレポであることから、shared/ディレクトリなどにこの仕様書を置いておけば、そこから存在しているファイルを読み込んで、バックエンド・フロントエンド一括でモデルを作成できることもポイントでしょう。これが、API仕様書から自動生成する方式がモノレポにおいて相性が良い大きな理由です。

OpenAPI仕様書からモデルを生成する

それでは、具体的にOpenAPI仕様書からモデルを生成するコードを見ていきましょう。

...とその前に、もうひとつWeb開発でおすすめのメソッドを紹介しておきます。

今回のプロジェクトでは、Makefileを用いてアプリのformatやlintを行っています。

Makefileは、プログラムのコンパイルおよびリンク方法を指示するためのスクリプトですが、意外にもWebのbuildやformat, lintコマンドを簡略化するのにも使えます。

check_format_backend:
	cd $(API_DIR) && ruff check .
	cd $(API_DIR) && ruff format .

check_format_frontend:
	@echo "🔍 Checking frontend code formatting..."
	npx @biomejs/biome format --write $(SRC_DIR)
	@echo "🔍 Linting frontend code..."
	npx @biomejs/biome lint $(SRC_DIR)

今回は以下のようにPHONY宣言でgenerate-modelsを定義します。

Makefileを用いることで、普段アプリのビルドなどにかかっている時間を大幅短縮できます。

.PHONY: generate-models
generate-models:
	bash scripts/generate_openapi_models_py.sh
	bash scripts/generate_openapi_models_ts.sh

上記の例ではmake generate-models をすると、その中に書かれている二つのスクリプトが実行されます。今回は、バックエンドにpython(Pydantic)、フロントエンドにTypeScriptを使っているため、それぞれの言語のモデルを生成するためにスクリプトが用意されているイメージです。

実際にコードを見てみましょう。下のコードは実際にpythonのpydantic modelを生成しているシェルスクリプト部分で、datamodel-codegenというツールを使っています。

https://github.com/koxudaxi/datamodel-code-generator

if uvx --from datamodel-code-generator datamodel-codegen \
  --input "$OPENAPI_FILE" \
  --input-file-type openapi \
  --disable-timestamp \
  --output "$OUTPUT_FILE" \
  --output-model-type pydantic_v2.BaseModel; then
  echo "✅ モデルファイルが生成されました: $OUTPUT_FILE"
else
  echo "❌ Error: Model generation failed."
  exit 1
fi

これによって、API仕様書からモデルを作成することができるようになりました。これをTypeScriptでもやっていきます。TypeScriptではopenapi-typescript を使用しています。

# openapi-typescript が未インストールなら追加
if ! npm list openapi-typescript > /dev/null 2>&1; then
  echo "ℹ️ openapi-typescript not found. Installing..."
  npm install openapi-typescript
fi

# npx を使用して、openapi-typescript コマンドを実行
if npx openapi-typescript "$OPENAPI_FILE" --output "$OUTPUT_FILE"; then
  echo "✅ モデルファイルが生成されました: $OUTPUT_FILE"
else
  echo "❌ Error: Model generation failed."
  exit 1

https://www.npmjs.com/package/openapi-typescript

これで、make generate-models を入力するだけで実際にOpenAPI仕様書からスキーマを生成・更新することができるようになります。

モノレポ構成とSSOT(Single Source Of Truth)は相性抜群

今回、API仕様書からのモデル自動生成の仕組みを整備したことで、APIの定義ないし実装がAPI仕様書と強く結びつき、API仕様書はAPI定義における「単一の信頼できる情報源(SSOT)」としての役割を果たすようになりました。

原則としてドキュメントは、その鮮度を保つことが最重要であり、そのためにはできる限り変更する対象のファイルが最小限になるように集約していくのが基本です。

SSOTの考え方は、汎用的な関数をモジュール化して再利用可能にしたり、ないしはレポジトリを一つにしてその同期や変更のコストを最小限に抑えることにも通底する概念かもしれません。

近年はいわゆるDevinやClaude Codeを用いた「AI駆動開発」がトレンドになっていますが、その際にもできるだけAIに対して読み込ませたいコンテキストの数が少ない方が精度が高まります。

実際に弊社でも、この仕組みを取り入れたことでAPIについて気にかけている時間はほとんどなくなったと思います。

もちろん導入の上ではプロジェクトの規模や全体の構成を踏まえる必要がありますが、比較的小規模なチームでモノレポ構成をとっている開発チームにはぜひお勧めしたいです!

おわりに

今回は、モノレポ環境においてOpenAPI仕様書を活用した型生成の仕組みを紹介しました。

モデルの自動生成やSSOTに基づいたスキーマの一元管理は、チームの生産性向上に直結する仕組みだと改めて実感しています。

こうした整備は一朝一夕にできるものではありませんが、「自分たちが開発しやすい環境を自分たちでつくる」という意識があれば、少しずつでも形にしていけると思っています。

株式会社ハイクリでは、今回ご紹介したような開発体験の改善にもチーム全体で積極的に取り組んでいます。

時系列データや在庫管理システムの構築、1から価値あるプロダクトを練り上げていく貴重な経験に関心があるエンジニアの方がいらっしゃれば、ぜひ気軽にご連絡ください!

一緒に働く仲間を探しています!

GitHubで編集を提案

Discussion