Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
NestJSのコードからOpenAPIを自動生成する際の最適解を探す
Search
Tatsuya Asami
March 17, 2025
Programming
0
220
NestJSのコードからOpenAPIを自動生成する際の最適解を探す
Tatsuya Asami
March 17, 2025
Tweet
Share
More Decks by Tatsuya Asami
See All by Tatsuya Asami
終わってる風終わってないタスクが自分の首を締めた話
astatsuya
0
410
Other Decks in Programming
See All in Programming
小田原でみんなで一句詠みたいな #phpcon_odawara
stefafafan
0
340
The Nature of Complexity in John Ousterhout’s Philosophy of Software Design
philipschwarz
PRO
0
110
Defying Front-End Inertia: Inertia.js on Rails
skryukov
0
490
Thank you <💅>, What's the Next?
ahoxa
1
480
RuboCop: Modularity and AST Insights
koic
2
1.3k
MCP調べてみました! / Exploring MCP
uhzz
2
2.3k
ComposeでWebアプリを作る技術
tbsten
0
110
Deoptimization: How YJIT Speeds Up Ruby by Slowing Down / RubyKaigi 2025
k0kubun
0
850
設計の本質:コード、システム、そして組織へ / The Essence of Design: To Code, Systems, and Organizations
nrslib
4
590
アプリを起動せずにアプリを開発して品質と生産性を上げる
ishkawa
0
2.8k
Qiita Bash
mercury_dev0517
2
200
音声プラットフォームのアーキテクチャ変遷から学ぶ、クラウドネイティブなバッチ処理 (20250422_CNDS2025_Batch_Architecture)
thousanda
0
210
Featured
See All Featured
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Embracing the Ebb and Flow
colly
85
4.6k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
It's Worth the Effort
3n
184
28k
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.7k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
30
2.3k
Site-Speed That Sticks
csswizardry
5
500
Speed Design
sergeychernyshev
29
900
GraphQLとの向き合い方2022年版
quramy
46
14k
Java REST API Framework Comparison - PWX 2021
mraible
30
8.5k
Writing Fast Ruby
sferik
628
61k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
26k
Transcript
© Commune Inc. All rights reserved NestJSのコードから OpenAPIを 自動生成する際の最適解を探す 2024/03/17
NestJS meetup #6 浅見 達也@astatsuya1 1
© Commune Inc. All rights reserved 浅見 達也 (@astatsuya1) •
仕事 ◦ コミューン株式会社 SuccessHub事業部 ▪ 2022年7月~2024年3月 CommuneのWebエンジニア ▪ 2024年4月~ SuccessHubのWebエンジニア • ペット ◦ デグー 自己紹介 2
© Commune Inc. All rights reserved 3 チームの生産性を圧倒的に向上し、カスタマーサクセス組織に成果をもたらす 顧客に関するあらゆる重要な 情報や健康状態を一元管理
テックタッチの工数で ハイタッチの効果を実現 顧客の状態に応じた個別最適な アクションを実行管理
© Commune Inc. All rights reserved • NestJSのコードからOpenAPIを自動生成する際の最適解を探す ◦ これまでやってきて苦戦したことを共有
◦ 道半ばながら辿り着いた最適解を共有 今日の発表内容 4
© Commune Inc. All rights reserved • 技術構成 ◦ バックエンドはNestJS(monorepo,
SWC)でREST API ◦ class-validator, class-transformerを使ってAPIリクエストのバリデーション や変換を行っている ◦ @nestjs/swaggerを使ってソースコードからOpenAPIを出力 ◦ フロントエンド(今回関係ない) ▪ Orvalを使ってOpenAPIからフロントエンドで使用するコード(型定義、データフェッチ、モックサーバー)を 自動生成 ▪ ブラウザからNestJSにHTTPリクエスト(BFFはない) 前提となる技術構成 5
© Commune Inc. All rights reserved 過去やってきたことを紹介します 1. @nestjs/swagger CLI
Pluginの導入をチャレンジ(失敗) a. 実装中にローカルサーバーがエラーで止まりまくる 2. @nestjs/swagger CLI Pluginを使わず、手動でデコレータを付ける(採用) a. 仕組みは出来たが不満あり 今までやってきた OpenAPIの自動生成への取り組み 6
© Commune Inc. All rights reserved ParametersとRequest bodyの出力 4. @nestjs/swagger
CLI Pluginを使わず、手動でデコレータを付ける 7 • リクエストボディ、リクエストパラメータは元々 dtoがあったので、ひたすら @ApiPropertyを つけるのみ • この例は単純だが、他の dtoなどをimportし て型定義に使っている場合はもっと色々記 述する ◦ 結構重要なポイントだが今回は割愛
© Commune Inc. All rights reserved Responseの出力のためにClassSerializerを剥がす 4. @nestjs/swagger CLI
Pluginを使わず、手動でデコレータを付ける 8 • ClassSerializerはクラスインスタ ンスをプレーンオブジェクトに変 換してくれる • 元々エンティティに変換処理のた めのデコレータをつけることがみ んな微妙だと思っていた(コント ローラーで行うべき処理) ので、あまりためらいなく剥がし た
© Commune Inc. All rights reserved Responseの出力のためにdto作成 4. @nestjs/swagger CLI
Pluginを使わず、手動でデコレータを付ける 9 • レスポンスは新たにレスポンス用の dtoを作 成 • レスポンスではバリデーションを行わない ので、OpenAPIのためだけに書いている
© Commune Inc. All rights reserved Response出力のためにコントローラーにデコレータを追加 4. @nestjs/swagger CLI
Pluginを使わず、手動でデコレータを付ける 10 • コントローラーの関数に @ApiOkResponseのデコレータを 追加 ◦ これをつけるとOpenAPIの Responseが出力される • コントローラーの関数の戻り値の型 にdtoを指定することで型安全にす る ◦ dtoにあるプロパティを書き忘 れたらエラーになる
© Commune Inc. All rights reserved 記述が多くて面倒だが、理論上完璧 4. @nestjs/swagger CLI
Pluginを使わず、手動でデコレータを付ける 11
© Commune Inc. All rights reserved • OpenAPIのためのデコレータの記述を間違えがち • 間違っていてもIDE上でエラー等は出ないので、気をつける、ちゃんと確認
する以外のソリューションがない • フロントエンド開発中にミスに気がつくと、バックエンドのコード修正をまず やらないといけないのが面倒 ◦ OpenAPIからフロントエンドのコードを自動生成をしているため、フロ ントエンドの型定義は手動で直せない 半年ほど運用してみて 12
© Commune Inc. All rights reserved かなり単純な記述でも忘れがち 今まで取り組んできたことの流れ 13
© Commune Inc. All rights reserved • @nestjs/swaggerのCLI Plugin導入に再チャレンジ ◦
NestJSのドキュメント通りに実装したところ ▪ 上手く出来ている • ローカルサーバーは動いている • OpenAPIのParameters, Request body, Responseはおおよそ出力されている様 子 ▪ 上手く出来ていない • 12件型エラーが出ている • コード変更しているとたまに型エラーが出る • ローカルサーバーの起動時間が約 3秒→約27秒になった 改善に向けて 14
© Commune Inc. All rights reserved ◦ 全て同じファイルにdtoが複数ある場合だった ▪ 単にファイル分割で対応完了
これでエラーがなくなった! 12件型エラーが出ている 15
© Commune Inc. All rights reserved • ファイル追加や削除、変数名を変更した場合にエラーが出やすい ◦ ローカルサーバーは止まっていないようなのでエラーを無視すれば開発自
体は出来るが気になる • エラー自体が起きないようにするのは難しそう エラーが起きたら復旧出来るようにする コード変更しているとたまに型エラーが出る 16
© Commune Inc. All rights reserved • エラーを起こしているmetadata.tsを上書きする単純なスクリプトを作成 ◦ metadata.tsはCLI
Pluginを使うと生成されるOpenAPIのためのファイル ◦ エラーが起きたらこのスクリプトを実行してリセット スッキリ解決はしてないけど、これでストレスはかなり軽減 コード変更しているとたまに型エラーが出る 17
© Commune Inc. All rights reserved • 流石に許せない ◦ SWCを入れる前と同じくらい時間がかかっている
OpenAPIを立ち上げないコマンドと、OpenAPIを立ち上げるコマンドを用意する ローカルサーバーの起動時間が約 3秒→約27秒になった 18
© Commune Inc. All rights reserved • OpenAPIを生成するときとしないときのnest-cliを作成 ◦ nest-cli.json(しない)とnest-cli-openapi.json(する)を作成
◦ コマンド実行時にファイルパスを指定する ローカルサーバーの起動時間が約 3秒→約27秒になった 19 SwaggerModule
© Commune Inc. All rights reserved • OpenAPIを使わない場合はSwaggerModuleも読み込まない ◦ metadata.tsを読み込まなければ速度はあまり変わらないが、不完全な
OpenAPIが見たいこと はない、混乱の元なので全部読み込まない • npm scripts(コマンド長い) ローカルサーバーの起動時間が約 3秒→約27秒になった 20 SwaggerModule
© Commune Inc. All rights reserved コマンドの使い分け • 普段のバックエンド開発では OpenAPIは生成しないで立ち上げ
◦ バックエンド開発中は OpenAPIをあまり見ないため ◦ ローカルサーバーは安定して欲しい、何度も起動するので速度も重要 • OpenAPIを見たい時、変更するときは OpenAPIを生成して立ち上げ ◦ 実装中にエラーが出たときはリセットコマンドで回避可能 ◦ プロダクションビルド (nest build)も遅くなるが、サーバーの起動速度はほぼ変わらなかったの で問題なし 少し苦しいがなんとか課題解決! ローカルサーバーの起動時間が約 3秒→約27秒になった 21 SwaggerModule
© Commune Inc. All rights reserved • dtoにあるOpenAPIには不要なプロパティに @ApiHidePropertyをつけていく ◦
toNameのような変換関数が主に不要な値 • 不要になった@ApiPropertyを消していく ◦ あっても問題ない。@ApiPropertyに記述してある値 が優先的に使われる ◦ 型定義が複雑な場合は引き続き指定する必要があ る 残りの作業は @ApiHidePropertyをつけていく 22
© Commune Inc. All rights reserved これで一通り完了! 23
© Commune Inc. All rights reserved ◦ dtoは1ファイルに1つのみ記載する ◦ dtoの各プロパティには基本的に@ApiPropertyをつけない。上手く出力されな
い場合にのみ@ApiPropertyを使って正しい値を自分で記述する ◦ dtoにあるOpenAPIには出力したくないプロパティには@ApiHidePropertyをつ ける 開発時に気にすることまとめ 24
© Commune Inc. All rights reserved • OpenAPIのために技術的な選択が必要だった ◦ ClassSerializerを剥がしたが、剥がしたくない場合は積んでいたかも
• コードからドキュメント(OpenAPI)が自動生成される一番嬉しい状態が作れた • 快適なローカル開発環境との両立は許容できる 総じて満足 道半ばながら辿り着いた最適解振り返り 25
© Commune Inc. All rights reserved NestJSとOpenAPIの話は以上です 最後に本件と関係ないけど気になっていること 26
© Commune Inc. All rights reserved • NestJSでそこまでコード量が多くないのにモジュールの読み込みに結構時間が かかるのをどう対処しているのか •
漏れがなく、負荷が少ない操作ログの設計 • MySQL, Prismaを使ってマルチテナントの実装する場合の工夫 • Visual Regression Testで何をどこまで確認しているか この後の懇親会で相談させてください!! 最後に本件と関係ないけど気になっていること 27
募集中の求⼈はこちら カジュアル⾯談も 実施しています! コミューン株式会社では共に働く仲間を募集中です ありがとうございました