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-tRPCと戦術的DDDのいいとこどりをしてバックエンドTypescriptの設計...
Search
与謝秀作
March 17, 2025
Technology
770
1
Share
NestJS-tRPCと戦術的DDDのいいとこどりをしてバックエンドTypescriptの設計をした話
与謝秀作
March 17, 2025
More Decks by 与謝秀作
See All by 与謝秀作
ジュニアエンジニアを戦力化する
yosashusaku
0
35
Other Decks in Technology
See All in Technology
AI時代に求められる思考のパラダイムシフト
nrinetcom
PRO
1
150
データ分析基盤の信頼を支える視点と設計
yuki_saito
1
650
ラズパイ & Picoで入門:Zephyr(RTOS)の環境構築からビルドまでの紹介
iotengineer22
0
230
Node.js+TypeScriptにおけるCJS/ESM相互運用の最新ポイント
grainrigi
2
120
TSKaigi 2026 - enumよ、さようなら
teamlab
PRO
3
540
TSKaigi 2026 - Auth.jsからBetter Authへの 移行に見る「型とランタイム」の 設計思想の変化
teamlab
PRO
1
260
老舗OCIクラウドインテグレーターが語る-現場で培ったクラウドリフトのリアルと成功のカギ
shinpy
0
120
責任あるソフトウェアエンジニアリングの紹介4章・5章 / RSE_Ch4-5
ido_kara_deru
0
330
Pythonでベイズモデリング
soogie
0
180
基礎から解説!Icebergで紐解くSnowflake×Databricks連携の現在地
cm_yasuhara
0
300
『家族アルバム みてね』における インシデント対応との向き合い方 / Approach incident response in Family Album
kohbis
2
180
生成AIに振り回されない 〜確率論と決定論の使い分け〜
shukob
0
110
Featured
See All Featured
Being A Developer After 40
akosma
91
590k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
10k
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
120k
We Are The Robots
honzajavorek
0
230
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
450
Learning to Love Humans: Emotional Interface Design
aarron
275
41k
Primal Persuasion: How to Engage the Brain for Learning That Lasts
tmiket
0
340
A Soul's Torment
seathinner
6
2.8k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
540
Code Reviewing Like a Champion
maltzj
528
40k
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.7k
Transcript
NestJS-tRPCと戦術的DDDのい いとこどりをしてBackend Typescriptの設計をした話 by Ficilcom CEO YOSA
自己紹介 東京大学工学部システム創成学科卒業 日鉄ソリューションズ(SIer) :システムエンジニア bestat(松尾研系スタートアップ) :機械学習エンジニア ZOZO(自社サービス) :推薦エンジニア 独立、現在2個目のプロダクトを開発中(今日はここの話) ←Web
DB Press vol.129 「レコメンドエンジン総実装」 ↓ https://zenn.dev/yosashusaku
祝!2年ぶりの開催 この2年でNestJSの(個人的に一番の)大きな変化といえば、、、
NestJS tRPCのローンチ(2024/06) https://www.nestjs-trpc.io/ tRPCの作者(KevinEdry) が開発 →Monorepo内のBackend Typescriptとして有力 な 候補に
tRPCとは client/serverでTS の型を共有 Monorepo前提 →とにかく開発体 験がいい!!
前提条件:Turborepoを使った開発 https://turbo.build/repo/ Vercel製のTS/JS専用Monorepo管理ツール - リモートキャッシュ - タスクの依存解決 - テストやビルドの並列実行 Monorepo開発における強力な機能が多い
(Full TS前提だと特におすすめ) pnpm workspaceの拡張で右図のような ディレクトリ構成になっている
NestJS tRPCの設定 apps/api/src/app.module.ts packages/trpc/@generatedに自動生成 →フロントから呼び出せる
NestJS tRPCの実装例 NestJS tRPC専用のデコレータ DTOの代わりに Zodでスキーマ定義 (InputとOutputに使う フロントと型を共有) このサンプルでは1ファイルに 書いているが、実際に
Module内は Router / Schema / Service で構成される。
NestJS tRPCのその他のメリット Validationの違い:Zodになったことでフロントと共有できるテクニックが使える class-validator → Zod
おまけ:tRPC-Panel Swagger UIのtRPC版 APIエンドポイントの Documentを自動生成
NestJSでもMonorepo構成を 活かしたtRPCによる開発体験を 得ることができるゾ さて、 NestJSを使った開発に入る前に
NestJSは巷で言われているように too much なフレームワークなのだろうか?
APIサーバの役割をDDDの層に分解すると
NestJSの機能を当てはめると Controller / Router DTO / Schema Service
Serviceファイルに詰め込み過ぎじゃない? Serviceファイルにドメイン層・ユースケース層・インフラ層の責務を持たせる (Fat Service問題)のは無謀ではないか →改修困難なコード、人によってバラツくコーディングルール NestJSがtoo muchというのは嘘だと思う ※むしろnot enoughに感じた
NestJSで足りない部分は戦術的DDDで補う DDDの部分はpackages/coreに切り出そう! →ドメイン層とユースケース層はapps/apiを離れて packages/coreに移動する。 apps/api:NestJS(DI、デコレータなど) packages/core:DDD(domain、usecase、error) それぞれの文脈で開発を言葉を分けられる
戦略的DDDの構成要素 ドメイン層 - ビジネスロジックをエンティティや値オブジェクトに閉じ込め、純粋なビジネスルール として実装します。 - entity / value-object /
aggregate / domain-service / repository(I/F) ユースケース層 - ユースケースに沿った処理を実装し、ドメイン層のオブジェクトを組み合わせてビジ ネスプロセスを実現します。 インフラ層 - 永続化や外部サービスとの連携など、技術的な実装を担います。ここでは、Prisma などのORMが利用され、実際のデータアクセスを管理します。
ドメイン駆動設計における依存の方向 api:ライブラリや外部アクセス (ORM等)に依存する core:純粋なビジネスロジックを表現 ライブラリ等に依存しない PureなTypescriptで実装する apiはcoreに依存する。 それぞれ分離することで、TestableでSOLIDな構成になる。
Turborepoを使った依存関係の管理 packages/core/package.json 余計なライブラリを入れない apps/api/package.json dependenciesでcoreへの依存を定義 core → api の順にtestやbuildを実行 DDDの依存関係をpackageで管理できた
依存方向のディレクトリ構成対応 ① ② ③ ① ② ③ ※依存元→依存先
依存性逆転の法則(実例) インフラ層を リポジトリに注入 (=依存性逆転) Repository(I/F) を使ってusecase を定義
依存性逆転の法則(実例解説) 前ページの実装例では AuthJSを活用して認証を行っているため、api配下ではAuthというModuleに属してい る。 ところが、core配下ではAuthJSというライブラリには依存したくないため、 ”createUser” といったビジネスドメインでの定義をしている。 ↓ core配下をPureなTypescriptを使って(=外部ライブラリやサードパーティに依存せず) ビジネスドメインを表現している。
いつでもNestJSを剥がせる (↑NestJSのmeetupで言うことじゃない!)
まとめ Tureborepoの性質をフル活かすことで、 ①NestJSでもtRPCという極上の開発体験を得られる ②NestJSとTS DDDのいいとこどりをした開発ができる
告知①:エンジニア募集中 Typescript DDDだけじゃなくて おもしろい技術スタック使ってるよ! 募集職種:Typescript芸人 プロダクトエンジニア 建設業というドメイン (→DDDを使いたかった)
告知②:TSKaigi 2025開催
ご清聴ありがとうございました