運用技術開発担当の辰已です。Generatorを利用してみました。ハートビーツの価値向上につながる社内のさまざまなプロダクトの開発・保守運用を行っています。ITインフラ・フロントエンド・バックエンドなど、さまざまな技術に触れながら技術開発や情報発信をしています。やりたいエンジニアにとっては非常におもしろい環境です。Generatorでできることフロントエンドとバックエンドを分離するとAPIの調整が面倒になりがちです。バックエンドで定義した型と同じ型をフロントエンドでも同じように定義したり、APIの仕様が変わったときにフロントエンドとバックエンドを漏れなく不具合なく変更したりするのは、なかなか骨の折れる作業です。Generatorを利用してみました。結果としては、面倒なコードの作成が自動化されていい感じです。APIのインターフェイス定義方法です。APIのリクエストとレスポンスがどのようなデータで構成されているのか、型が何かといったインターフェイスのフォーマットを言語に依存せず定義できます。この定義ファイル(以降スキーマファイルと呼びます)はYAML形式あるいはJSON形式で記述します。今回のサンプルコードではJSONを利用しています。GeneratorとはOpenAPIのスキーマファイルを読み込み、さまざまな言語のAPIクライアント(※1)を自動生成してくれるツールです。スキーマファイルの内容に沿ったリクエストとレスポンスの型定義や、リクエスト実行の関数定義などを自動生成してくれます。※1)この「クライアント」は「フロントエンド」の意味ではなく「APIの呼び出し元」という意味です。バックエンドのコードでもAPIを呼び出すコードのことを「APIクライアント」と呼びます。Generator関連で「クライアント」と記載されていた場合は「フロントエンド」を意図していない場合があるのでご注意ください。今回のサンプルコードの構成です。現在開発中のプロダクトも同じような構成で作成しています。あるフロントエンドとバックエンドを分離する構成です。フロントエンドはTypeScriptでNext.jsを利用しています。フロントエンドはTypeScript、フレームワークとしてNext.jsを選択することが多いです。バックエンドではPythonやGoを利用することが多いですが、性能が求められるような場所ではRustを利用することもあります。Generatorを利用した開発のフローには「スキーマファースト」「コードファースト」の2種類が存在します。スキーマファーストの開発フローでは以下の流れで開発します。自動生成したクライアントを利用して、フロントエンドとバックエンドを作成スキーマファイルさえ定義してしまえば、フロントエンドとバックエンドを並行で開発できるのがメリットです。スキーマファイルを書くための学習コストがかかってしまうのがデメリットです。コードファーストの開発フロー(※2)では以下の流れで開発します。自動生成したクライアントを利用して、フロントエンドを作成コードからスキーマファイルを生成するので、OpenAPIのことをあまり意識することなくスキーマファイルを生成できるのがメリットです。コードが作成できないとスキーマファイルを生成できないので、スキーマファーストのように並列で開発しにくいことがデメリットです。今回サーバーで利用しているFastAPIはOpenAPIに準拠して設計されているため、ほぼOpenAPIの学習なしでスキーマファイルを生成できます。今回の開発は少人数で融通が効きやすかったので、コード作成が進まずにスキーマファイルが出力できない、といったリスクもありませんでした。そのため、今回はコードファーストのフローで開発を進めることにしました。※2)フロントエンドを先に開発し、そこからスキーマファイルを出力する流れも可能ですが、あまりすることはないかもしれません。バックエンドの作成FastAPIを用いてバックエンドを実装するだけです。定義といってもPythonを実装するだけです。以下はItemのデータを返すエンドポイントのサンプルコードです。tax=1)OpenAPIの記法をまったく意識せず作成できるのはすごいですね。注意点として、エンドポイントの引数と返り値の型は明記する必要があります。型を記載しなかった場合には、コードを正しく出力できないことがあります。スキーマファイルの出力バックエンドのアプリケーションを起動し、openapi.jsonのURLにアクセスすればスキーマファイルを取得できます。今回のサンプルコードであればURLはhttp://127.0.0.1:8080/openapi.jsonになります。毎回バックエンド起動・URLにアクセス・コピペは面倒です。そこで、以下のようなpythonコードを作りました。コマンド一発でスキーマファイルの内容を出力できるので快適です。json.dumps(app.openapi())print(j)フロントエンドの作成フロントエンドはスキーマファイルから自動生成したクライアントを利用します。Generatorが自動生成してくれます。Generatorのコマンドにスキーマファイルを渡すだけでコードが自動生成されます。Generatorでtypescript-axiosを利用し、コードを自動生成する例です。GeneratorはJava製のため実行するためにはJavaをインストールする必要があります。フロントエンドの開発コンテナにJavaを入れることも可能ですが、ツールのために環境を変更するのはちょっと気が引けます。Generator用のDockerイメージが公式から配布されていたので、こちらを利用することにしました。openapitools/openapi-generator-cli今回のサンプルコードではフロントエンドも開発コンテナを利用しています。Generatorコンテナを操作できるようにしました。以下のスクリプトを実行することでtypescript-axiosの形式でコードを自動生成できます。ディレクトリやコンテナ名は今回のサンプルに合わせて設定しています。Generatorを利用できるようになりました。クライアントの利用クライアントの生成で出力したコードをフロントエンドのコードから利用します。今回、自動生成されたコードはopenapi_front_sample/src/openapi/typescript-axiosに出力しています。いろいろなファイルが自動生成されますが、主に利用するのはapi.tsです。このファイルの中にはスキーマファイルで定義していた型定義やリクエスト用関数などが出力されます。今回のサンプルでは5つの定義がexportされています。ItemDefaultApiAxiosParamCreatorDefaultApiFpDefaultApiFactoryDefaultApiItemはFastAPI側で定義していたレスポンスのモデルの型です。DefaultApiAxiosParamCreatorはリクエスト実行時のパラメーター生成用関数です。DefaultApiFp、DefaultApiFactory、DefaultApiはリクエスト実行用のインターフェイスです。インターフェイスは3種類ありますが、処理内容はどれも同じで書き方が異なるだけです。使う側のフォーマットに合わせて選択すればOKです。今回のサンプルではDefaultApiFactoryを利用しました。...APIから取得したデータはuseSWRを用いて処理しています。レスポンスのデータ型やエンドポイント用関数が自動生成されているので、それらを呼び出すだけで型に守られたAPI呼び出しが可能です。動作確認フロントエンドとバックエンドのサンプルリポジトリにあるREADMEに従い、それぞれのアプリケーションを起動してみてください。起動後にブラウザからhttp://127.0.0.1:8080にアクセスすると、フロントエンドからバックエンドのAPIを呼び出した結果が表示されます。自動生成したクライアントをフロントエンドから利用これだけで簡単にコードが作れてしまいました。インターフェイスに仕様変更が発生した場合は、再度スキーマファイルを出力してコードを自動生成すればよいだけです。今回の例ではフロントエンドはTypeScriptを利用しているので型に守られています。インターフェイスの形式が変わった場合、もし変更漏れがあればビルド時にエラーが発生するので安心です。Generatorを用いたクライアントコードの自動生成について紹介しました。コード生成の自動化により作業の効率化や不具合の発生を抑止できるので、開発を効率化したい方にはメリットの多いツールではないかと思います。他にも運用技術開発担当では、さまざまな技術やツールを活用して日々の業務の効率化や技術開発を行っています。ITインフラだけでなくこのような部門もあるんだなー、ということが少しでも伝われば幸いです。株式会社ハートビーツの技術情報やイベント情報などをお届けする公式ブログです。こちら「みんな仲良く」「プライドを持って」「変化を楽しむ」という企業理念に共感していただけるエンジニアを募集しています。