0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

エアークローゼットAdvent Calendar 2024

Day 17

Nestjsプロバイダーのインジェクションスコープの留意事項

Last updated at Posted at 2024-12-23

みなさまこんにちは!エアークローゼットのLuckyです。この記事はエアークローゼットのアドベントカレンダー2024の17日目の記事となってます。

Nestjs injection scope's things to note

Nestjsとは

NestJSは、効率的で拡張性が高く、メンテナンスが容易なサーバーサイドアプリケーションを構築するための人気フレームワークです。

この記事では、Nestjsのインジェクションスコープの側面に焦点を当てます。Nestjsについて詳しく知りたい場合は、この記事を読むか、Nestjs の公式ドキュメントで学習できます。

NestJS Singleton - Injection Scope

Nestjsを使ったことがあるなら、おそらくインジェクションについてよく知っているでしょう。

プロバイダーに@Injectableデコレーターを定義すると、このプロバイダーのライフサイクルの制御をIoCコンテナー(Inversion of Control)に与えることになります。プロバイダーを使用するには、通常どおり、プロバイダーをコンストラクターに挿入し、モジュールに配置します。

IoCコンテナは、インジェクションスコープと呼ばれる機能を含む強力なプロバイダ管理をサポートします。

インジェクションスコープ(Injection Scope):

プロバイダーのスコープはそのライフサイクルを決定します。NestJSは主に以下の3つのスコープをサポートします:

  • Singleton Scope(SINGLETON): デフォルトスコープで、同じインスタンスがどこでも再利用されます。
  • Request Scope(REQUEST): 各リクエストごとに新しいインスタンスが作成されます。
  • Transient Scope(TRANSIENT): プロバイダーが注入されるたびに新しいインスタンスが作成されます。

以下と同様の方法で各プロバイダーのスコープを定義できます。

import { Injectable, Scope } from '@nestjs/common';

// ほとんどの場合、プロバイダーが特別な状態を保存しない場合は、
// SINGLETONスコープ (デフォルト) を使用することになります。
@Injectable({ scope: Scope.REQUEST })
export class CatsService {}

singletonを使用すべき

ほとんどの場合、プロバイダーが特別な状態(state)を保存しない場合は、 SINGLETON スコープ (デフォルト) を使用する必要があります。

なぜそうなるのかというと、Nestjsがプロバイダーのインスタンスを作成するときに、それが SINGLETON スコープの場合、このインスタンスはインポート先のモジュール全体で共有されるからです。

多くのメリットがありますが、特に次の2つのメリットがあります。

  • モジュールでは各プロバイダーのインスタンスが1つだけなのでメモリを節約できます。

  • 各呼び出し後に作成されるインスタンスが多すぎると、処理が完了したときにクリーンアップするためgarbage-collectionシステムでCPUリソースが浪費されるため、インスタンスが1つだけでリソースが節約されます。

image.png

留意事項

インジェクションスコープを効果的に使用するために、以下の留意事項もあります。

スコープの階層(Scope hierarchy)

プロバイダーのスコープを定義する際に留意すべきことが1つあります、それは、スコープの階層です。

簡単に言うと、コントローラーまたはプロバイダーのスコープは SINGLETON が、スコープが REQUEST であるクラスに依存している場合、依存するプロバイダーまたはコントローラーのスコープは REQUEST に変更されます。

次のようなインジェクションチェーンがあるとします。
CatsControllerCatsServiceCatsRepository
CatsControllerCatsServiceSINGLETON スコープがあるが、CatsRepositoryREQUEST スコープがある場合、CatsServiceCatsController の両方のスコープが REQUEST に強制的に切り替えられます。

たとえば、CatsRepository内の REQUEST にアクセスしたいため、@nestjs/coreREQUEST プロバイダーを使用する場合 、このプロバイダーには REQUEST のスコープがあるため、誤ってインジェクション チェーン全体が REQUEST のスコープに切り替わってしまいます。

したがって、 REQUEST スコープは絶対に必要な場合にのみ使用すべきと思います。

モジュール管理

Nestjs では、プロバイダーをモジュールにインポートすると、そのプロバイダー インスタンスは、インポート先のモジュール全体で使用されます。ただし、いくつかモジュールが同じプロバイダーを使用する場合は、これらのモジュールが同じプロバイダーのインスタンスを使用できるようにすべきです。

たとえば、子モジュールAと子モジュールBに同じ親がある場合、子モジュールの両方が同じプロバイダーをインポートするのではなく、そのプロバイダーを子モジュールAからエクスポートしてから、子モジュールBにインポートすることをお勧めします(shared modules機能)。そうすれば、両方で同じインスタンスを使用してリソースを節約できます。

モジュールの管理と最適化を簡単にするために、nestjs-spelunker ライブラリを使用して NestJs の依存関係(Dependencies)を視覚化できます。

最後に

NestJS は、簡単に拡張および保守できるフレームワークです。さらに、IoC のおかげで、アプリケーションの実行時のリソースの最適化にも役立ちます。

NestJS を使用する開発者にとって、NestJS の機能を正しく活用する方法を理解することは、システムを最適化し、ユーザーエクスペリエンス (UX) を向上させ、より良いユーザー体験を提供するために役立ちます。

また、エアークローゼットはエンジニア採用活動も行っておりますので、興味のある方はぜひご覧ください!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?