Nest.js 따라하기 (3) - Providers

Seok·2021년 5월 4일
0

Nest.js 따라하기

목록 보기
2/3
post-thumbnail

이 시리즈는 Nest.js 공식 Document를 바탕으로 따라해보며 내용들을 요약 정리한 게시글입니다.


1.Providers

Providers 는 Nest의 기본이되는 개념이다. Provider의 주된 아이디어는 의존성을 주입할 수 있다는 것이다. 이는 객체가 서로 다양한 관계를 만들 수 있다는 것을 의미하며, 객체 인스턴스의 Wiring up 기능은 주로 Nest 런타임 시스템에 위임될 수 있다.

이전 예제에서 간단한 CatsController를 만들었다. Controller는 HTTP요청을 처리하고 더 복잡한 작업을 Provider에게 위임해야한다. Provider는 모듈에 providers로 선언되는 일반 Javascript 클래스이다.


2. Services

CatsService를 작성해보자. 이 서비스는 데이터 저장 및 검색을 담당하며, CatsController가 사용하도록 설계되었으므로 제공자로 정의하기에 적합한 서비스이다.

CatsService.ts

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

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

  create(cat: Cat) {
    this.cats.push(cat);
  }

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

CatsService는 한개의 property 와 두개의 methods로 구성되어있다. 유일한 새로운 기능은 @Injectable() 데코레이터를 사용한 것이다. @Injectable() 데코레이터는 메타데이터를 첨부하여 CatService가 NestIoC 컨테이터에서 관리할 수 있는 클래스임을 선언한다. 그런데 이 예제에선 Catinterface도 사용한다. 이 인터페이스는 다음과 같다.

interfaces/cat.interface.ts

export interface Cat {
  name: string;
  age: number;
  breed: string;
}

CatsService는 클래스 생성자를 통해 주입된다. private syntax를 주의해야한다. 이 shorthand(?)는 CatsSerive member를 동일한 위치에서 즉시 선언과 초기화 한다.


3. Dependency injection

Nest는 일반적으로 Dependency injection이라고 알려진 강력한 디자인 패턴을 중심으로 구축된다.
Nest에서는 Typescript 기능 덕분에 의존성 관리가 매우 쉽다. 아래의 예시에서 Nest는 CatsServcie의 인스턴스를 만들고 반환함으로써 CatService를 해결한다.(또는 일반적인 싱글톤의 경우 이미 다른곳에서 요청한 존재하는 인스턴스를 반환한다.) 이 의존성이 해결되어 컨트롤러의 생성자에게 전달된다.(혹은 할당된다.)

constructor(private catsService: CatsService) {}

4. Scopes

Providers는 일반적으로 수명("범위")를 가진다. application이 bootstrapped(?)되었을때 모든 의존성은 해결되어야만 하므로 모든 provider는 인스턴스화 해야한다. 비슷하게, application이 종료될 때 각 Provider는 제거된다. 그러나, provider의 요청 범위의 lifetime을 지정할 수 있다.


5. Custom providers

Nest는 provider간의 관계를 해결하는 제어 컨테이너가 내장되어있다. 이 기능은 위에서 설명한 의존성 주입 기능의 기본이지만, 실제로 지금까지 설명한 것보다 훨씬 강력합니다. 공급자를 정의하는 방법에는 여려 가지가 있다. 일반 값, 클래스 및 비동기 또는 비동기 팩토리를 사용할 수 있다.


6. Optional providers

경우에 따라서 반드시 해결해야할 필요가 없는 의존성이 있을 수 있다. 예를 들어 클래스는 구성에따라 다를 수 있지만 전달된 항목이 없으면 기본값을 사용해야한다. 이 경우 Configuration provider가 없어도 오류가 발생하지 않으므로 종속성은 선택 사항이 된다.

공금자가 선택사항임을 나타내려면 생성자 서명에 있는 @Opion() 데코레이터를 사용해라.

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

@Injectable()
export class HttpService<T> {
  constructor(@Optional() @Inject('HTTP_OPTIONS') private httpClient: T) {}
}

위의 예시에서는 HTTP_OPTIONS custom token을 사용하고 있으므로, custom provider를 사용했다. 이전 예시에서는 생성자 기반 주입이 생성자의 클래스를 통한 의존성을 나타내는 것을 보여주었다.


7. Property-based injection

지금까지 사용한 기술은 provider가 생성자 함수를 통해서 주입되기 때문에 생성자 기반 주입이라고 불린다. 어떤 특정한 경우 속성기반 주입이 유용할 수 있다. 예를들어 최상위 클래스가 하나 또는 여러 제공자에 종속되어 있는 경우 해당 클래스를 끝까지 전달하는 것은 매우 지루할 수 있다. 이 문제를 방지하려면 속성 수준에서 @Inject()데코레이터를 사용할 수 있다.

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

@Injectable()
export class HttpService<T> {
  @Inject('HTTP_OPTIONS')
  private readonly httpClient: T;
}

8. Provider registration

이제 우리는 Provider(CatsService)를 정의 했고, 그 서비스의 소비자(CatsController)를 가지고 있기 때문에, Nest가 주입을 수행할 수 있도록 서비스를 등록해야 한다. 이 작업은 모듈파일(app.module.ts)을 편집하고 @Module() 데코레이터의 Provider배열에 서비스를 추가해서 수행한다.

app.module.ts

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 {}

Nest는 이제 CatsController 클래스의 의존석을 해결할 수 있다.
아래는 디렉터리 구조이다.


9. Manual instantiation

지금까지 우리는 Nest가 의존성 해결의 대부분의 세부사항을 자동으로 처리하는 방법에 대해 논의 했다. 경우에 따라 기본 제공 의존성 주입 시스템을 벗어나 수동으로 공급자를 검색하거나 인스턴스화해야 할 수도 있습니다. 우리는 아래의 두가지 주제에 대해 간략이 논의한다.

기존 인스턴스를 가져오거나 Provider를 동적으로 인스턴스화하려면 모듈 참조를 사용할 수 있다.

bootstrap()기능 내의 Provider를 가져오려면 독립 application을 참조하라.


출처

Nest.js 공식 Document

profile
🦉🦉🦉🦉🦉

0개의 댓글