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
320
NestJSのコードからOpenAPIを自動生成する際の最適解を探す
Tatsuya Asami
March 17, 2025
Tweet
Share
More Decks by Tatsuya Asami
See All by Tatsuya Asami
終わってる風終わってないタスクが自分の首を締めた話
astatsuya
0
430
Other Decks in Programming
See All in Programming
エラーって何種類あるの?
kajitack
5
310
GraphRAGの仕組みまるわかり
tosuri13
8
480
プロダクト志向なエンジニアがもう一歩先の価値を目指すために意識したこと
nealle
0
110
0626 Findy Product Manager LT Night_高田スライド_speaker deck用
mana_takada
0
110
Composerが「依存解決」のためにどんな工夫をしているか #phpcon
o0h
PRO
1
230
AWS CDKの推しポイント 〜CloudFormationと比較してみた〜
akihisaikeda
3
310
すべてのコンテキストを、 ユーザー価値に変える
applism118
2
810
今ならAmazon ECSのサービス間通信をどう選ぶか / Selection of ECS Interservice Communication 2025
tkikuc
20
3.6k
Benchmark
sysong
0
270
エンジニア向け採用ピッチ資料
inusan
0
160
Google Agent Development Kit でLINE Botを作ってみた
ymd65536
2
190
PHPでWebSocketサーバーを実装しよう2025
kubotak
0
160
Featured
See All Featured
Faster Mobile Websites
deanohume
307
31k
Docker and Python
trallard
44
3.4k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.7k
Into the Great Unknown - MozCon
thekraken
39
1.9k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
48
2.8k
The World Runs on Bad Software
bkeepers
PRO
69
11k
The Pragmatic Product Professional
lauravandoore
35
6.7k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Balancing Empowerment & Direction
lara
1
370
Stop Working from a Prison Cell
hatefulcrawdad
270
20k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
657
60k
Fantastic passwords and where to find them - at NoRuKo
philnash
51
3.3k
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
募集中の求⼈はこちら カジュアル⾯談も 実施しています! コミューン株式会社では共に働く仲間を募集中です ありがとうございました