[Nest.js] Dependency Injection

Donghun Seol·2023년 4월 20일
0

레퍼런스

https://docs.nestjs.com/fundamentals/custom-providers

위 링크의 글을 번역해보면서 네스트의 DI와 Provider, IoC의 작동 원리에 대해 학습하는 포스트 입니다.
아래의 형식으로 작성하였습니다.

This is original text

여기에 번역한 문장을 적습니다.

DI fundamentals

Dependency injection is an inversion of control (IoC) technique wherein you delegate instantiation of dependencies to the IoC container (in our case, the NestJS runtime system), instead of doing it in your own code imperatively. Let's examine what's happening in this example from the Providers chapter.

의존성 주입은 제어의 역전 기법으로 의존성의 인스턴스화를 코드에서 명시적으로 하는 대신 IoC컨테이너에 위임하는 것입니다. 아래의 프로바이더 챕터의 예시에서 자세히 알아보겠습니다.

First, we define a provider. The @Injectable() decorator marks the CatsService class as a provider.

먼저 우리는 프로바이더를 @Injectable() 데커레이터로 정의합니다.

cats.service.tsJS

import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';

@Injectable()
export class CatsService {
  private readonly cats: Cat[] = [];

  findAll(): Cat[] {
    return this.cats;
  }
}

Then we request that Nest inject the provider into our controller class:

그 다음 우리는 네스트에게 컨트롤러 클래스에 프로바이더를 주입해달라고 요청하게 됩니다.

cats.controller.tsJS


import { Controller, Get } from '@nestjs/common';
import { CatsService } from './cats.service';
import { Cat } from './interfaces/cat.interface';

@Controller('cats')
export class CatsController {
  constructor(private catsService: CatsService) {}

  @Get()
  async findAll(): Promise<Cat[]> {
    return this.catsService.findAll();
  }
}

Finally, we register the provider with the Nest IoC container:

마지막으로 프로바이더를 네스트 IoC 컨테이너에 등록합니다.

app.module.tsJS


import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';
import { CatsService } from './cats/cats.service';

@Module({
  controllers: [CatsController],
  providers: [CatsService],
})
export class AppModule {}

What exactly is happening under the covers to make this work? There are three key steps in the process:

내부적으로 어떤 원리로 위와 같은 동작이 가능할까요? 여기에는 세 가지 주요 절차가 있습니다.

In cats.service.ts, the @Injectable() decorator declares the CatsService class as a class that can be managed by the Nest IoC container.
In cats.controller.ts, CatsController declares a dependency on the CatsService token with constructor injection:constructor(private catsService: CatsService)

cats.service.ts 파일에서 @Injectable() 데커레이터는 CatsService 클래스가 네스트 IoC 컨테이너가 관리할 수 있는 클래스로 만들어줍니다. cats.controller.ts 파일에서 다음과 같이 생성자 주입으로 CatsService에 대한 의존성을 선언해줍니다: constructor(private catsService: CatsService)

In app.module.ts, we associate the token CatsService with the class CatsService from the cats.service.ts file. We'll see below exactly how this association (also called registration) occurs.

app.module.ts 파일에서 우리는 CatsService라는 토큰(또는 변수 명)을 cats.service.ts파일의 CatsService라는 클래스와 연결시켰습니다. 아래에선 어떻게 이런 연관(또는 등록)이 일어나는지 살펴보겠습니다.

When the Nest IoC container instantiates a CatsController, it first looks for any dependencies*. When it finds the CatsService dependency, it performs a lookup on the CatsService token, which returns the CatsService class, per the registration step (#3 above). Assuming SINGLETON scope (the default behavior), Nest will then either create an instance of CatsService, cache it, and return it, or if one is already cached, return the existing instance.

네스트의 IoC 컨테이너가 CatsController를 인스턴스화 할때, 의존성을 스캔합니다. 위의 예시에선 CatsService라는 토큰을 찾게됩니다. CatsService는 cats.service.ts파일의 CatsService클래스와 app.module.ts 파일의 설정을 통해 연관되어 있습니다. 기본동작인 싱글턴 스코프에서 네스트는 CatsService의 인스턴스가 있다면 캐시된 인스턴스를 반환하고, 없다면 생성, 캐싱, 반환의 절차를 통해 인스턴스를 전달해줍니다.

*This explanation is a bit simplified to illustrate the point. One important area we glossed over is that the process of analyzing the code for dependencies is very sophisticated, and happens during application bootstrapping. One key feature is that dependency analysis (or "creating the dependency graph"), is transitive. In the above example, if the CatsService itself had dependencies, those too would be resolved. The dependency graph ensures that dependencies are resolved in the correct order - essentially "bottom up". This mechanism relieves the developer from having to manage such complex dependency graphs.

위 설명은 요점을 설명하기 위해 간소화된 형태입니다. 우리가 오해를 피하기 위해 매번 강조하는 것은 의존성을 설정하기 위해 코드를 분석하는 과정은 매우 복잡하고, 어플리케이션의 부트스트랩 과정에 일어압니다. 의존성 분석의 중요한 부분은 이행적이라는 것입니다. 위의 예시에서 CatsService도 (생성자를 통해 주입되는 등의) 의존성을 가지고 있다면 그것도 해결(부트스트래핑 과정에서 인스턴스화 되어 클래스 내에서 참조할 수 있음을 의미)되었을 것입니다. 네스트의 의존성 그래프는 의존성들이 올바른 순서(상향식으로)로 설정되는 것을 보장합니다. 이런 메커니즘이 개발자가 복잡한 의존성 그래프를 관리해야하는 작업을 하지 않도록 도와줍니다.

profile
I'm going from failure to failure without losing enthusiasm

0개의 댓글