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
160
NestJSのコードからOpenAPIを自動生成する際の最適解を探す
Tatsuya Asami
March 17, 2025
Tweet
Share
More Decks by Tatsuya Asami
See All by Tatsuya Asami
終わってる風終わってないタスクが自分の首を締めた話
astatsuya
0
400
Other Decks in Programming
See All in Programming
読もう! Android build ドキュメント
andpad
1
190
Node.js, Deno, Bun 最新動向とその所感について
yosuke_furukawa
PRO
6
3k
マルチアカウント環境での、そこまでがんばらない RI/SP 運用設計
wa6sn
0
220
コンテナでLambdaをデプロイするときに知っておきたかったこと
_takahash
0
130
OUPC2024 Day 1 解説
kowerkoint
0
380
requirements with math
moony
0
500
remix + cloudflare workers (DO) docker上でいい感じに開発する
yoshidatomoaki
0
110
Django for Data Science (Boston Python Meetup, March 2025)
wsvincent
0
180
Gunma.web #55
tinykitten
0
130
アーキテクトと美学 / Architecture and Aesthetics
nrslib
11
2.8k
The Evolution of Enterprise Java with Jakarta EE 11 and Beyond
ivargrimstad
0
520
複数ドメインに散らばってしまった画像…! 運用中のPHPアプリに後からCDNを導入する…!
suguruooki
0
400
Featured
See All Featured
A Tale of Four Properties
chriscoyier
158
23k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
jQuery: Nuts, Bolts and Bling
dougneiner
63
7.7k
The Language of Interfaces
destraynor
156
24k
Speed Design
sergeychernyshev
28
850
The Invisible Side of Design
smashingmag
299
50k
GraphQLとの向き合い方2022年版
quramy
45
14k
Measuring & Analyzing Core Web Vitals
bluesmoon
6
320
Agile that works and the tools we love
rasmusluckow
328
21k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
129
19k
RailsConf 2023
tenderlove
29
1k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
45
9.5k
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
募集中の求⼈はこちら カジュアル⾯談も 実施しています! コミューン株式会社では共に働く仲間を募集中です ありがとうございました