NestJS
Overview
Nest を使用すると、オブジェクト指向で依存関係を設計および整理できるため、SOLID 原則に従うことを強くお勧めされている。
NestJSを使う意義
NestJSを使う意義は、現在主流となっているReactやVue、Svelteと同じTypeScriptで書けるということにある。
バックエンドでもフロントエンドと同じTypeScriptが使えるということが非常に貴重。
例えば人数やサービスの都合でフロントエンドとバックエンド、両方を受け持つメンバーが出たとする。
その際に、フロントエンドはReactのTypeScript、バックエンドはDjangoのPythonと使う言語が異なると、頭を切り替えて望まなくてはならない。
実際二つを掛け持ってみて、 文法やライブラリ、関数の違いが効き、生産性が落ちるという経験などがある。
同じ言語、文法で書けるというのは、両方やる人にとって大きなメリットになることは間違いない。
もしくはバックエンドのメンバーが足りず、 ReactやSvelteなどでTypeScriptは書けるというメンバーにNestJSを担当してもらうということもできる。
NestJSの大元のNode.jsの中に組み込まれているV8エンジンはC++で書かれていて、サーバー部分は速いと言われている。 しかし、他のスクリプト言語でも一部CやC++の力を借りて高速化の工夫があったりと一概に速いとは言えない。 また、Node.jsは非同期処理、平行処理で速く裁けると言われていたが、他のフレームワークでも平行処理に対応してきている。 例えばDjangoは、ASGIという非同期処理に対応したServer Gateway Interfaceに対応し、速くなってきている。 結局スクリプト言語同士では、原理的には大きな差が生まれない。 処理速度は多少は速いかもしれないが、それで選ぶという訳ではないだろう。 結局のところ、フロントエンドと同じTypeScriptで書けるというのが、NestJSを使う意義と言える。
NestJSの用語
providers: モジュール内で使うために登録するexports: 他のモジュールからも使えるように公開する
NestJSのDI(依存性注入)システムでは、「Provider」と「Export」という概念が非常に重要
Providerとは
provider とは、NestJSアプリケーション内で注入可能なクラスや値、ファクトリ関数などを指す。
たとえば、サービスクラスをDIコンテナに登録して他のクラスから使えるようにする場合、以下のようにモジュールで宣言。
@Module({
providers: [MyService],
})
export class MyModule {}
こうすることで、NestJSは MyService のインスタンスを生成し、必要な場所に自動的に注入してくれます。これは「依存性注入(DI)」の基本的な仕組みです。
provider:何かを提供する人・もの(=この場合はクラスや関数)
provide:提供する(動詞)
Exportとは
exports は、あるモジュール内で提供されたProviderを、他のモジュールでも使えるようにするための設定。
例えば MyModule で定義された MyService を他のモジュールでも使いたい場合
@Module({
providers: [MyService],
exports: [MyService],
})
export class MyModule {}
これで、別のモジュールが MyModule を imports することで MyService を使えるようになrう。
@Module({
imports: [MyModule],
})
export class OtherModule {}
つまり、**providers は「このモジュールの中で使えるようにするもの」であり、exports は「他のモジュールにも使わせてあげるもの」**という違いがあります。
NestJS API実装
NestJS で言う「非同期性」は大きく分けて2種類ある
// 1. Promise を返す関数(一般的な非同期API)
@Get()
async findAll(): Promise<any[]> {
return await this.service.fetchAll();
}
- 典型的な「非同期API」
- 非同期で1回だけ値を返す
- 決済の完了チェックなどに最適
// 2. Observable を返す関数(監視・ストリーミングAPI)
@Get()
findAll(): Observable<any[]> {
return of([]);
}
// または
@Get('status/:id/stream')
getStatusStream(@Param('id') id: string): Observable<PaymentStatus> {
return this.paymentStatusService.streamStatus(id); // RxJS の stream
}
- 値のストリーム(状態の変化など)に対応
- NestJS が内部で .subscribe() して最後の値をクライアントに返す
- SSE(Server-Sent Events)や WebSocket の実装とも親和性あり
✅ Promise と Observable の違いと使い分け
| 特徴 | Promise | Observable (RxJS) |
|---|---|---|
| 非同期処理 | ✅ 1回の非同期処理 | ✅ 複数回・連続的な非同期処理 |
| キャンセル可能 | ❌ | ✅ |
| 値の流れ | 単発(1回だけ) | ストリーム(0回以上、連続可能) |
| 例 | Stripe決済の結果を一度だけ取得 | ステータスの変化を監視して通知 |
RxJSの「監視可能なストリーム」は非同期処理の1つであり、“状態の変化を待つ” 構造に特に向いている
NestJSでリアルタイム通知を行う方法
- RxJSのObservable + SSE (Server-Sent Events)
- 軽量リアルタイム通信に最適、1方向通信
- WebSocketモジュール(@nestjs/websockets)
- 双方向通信が必要ならこちら