Provider란
Provider는 Nest에서 가장 중요한 개념입니다.
기본 Nest 클래스 중 상당수는 service, repository, factory, helpers 등 거의 모든 것이 Provider로 취급될 수 있습니다.
Provider의 주요 아이디어는 종속성으로 주입(dependency Injection) 될 수 있다는 것입니다.
이는 객체가 서로 다양한 관계를 생성할 수 있으며 이러한 객체를 "연결(wiring up)"하는 기능이 주로 Nest 런타임 시스템에 위임(delegated)될 수 있음을 의미합니다.
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;
}
}
* 메타데이터란
코드에서 특정 정보나 속성을 설명하기 위해 사용하는 추가 데이터를 의미합니다.
프로그래밍에서 메타데이터는 코드의 동작이나 구조에 관한 정보를 제공합니다.
TypeScript와 NestJS에서 데코레이터를 통해 클래스나 메서드에 메타데이터(injectable())를 부착하여 사용합니다
다시 말하면, @Injectable()를 붙여 클래스가 의존성 주입 컨테이너에 의해 관리될 수 있는 프로바이더임을 나타냅니다.
위의 예시의 경우 Injectable() 메타데이터를 서비스 클래스에 붙인 간단한 예시입니다.
이를 통해 NestJS IoC(Inversion of Control) 컨테이너에 의해 해당 클래스를 인식하고 인스턴스화할 수 있도록 합니다.
그래서 CatsService 클래스에 @Injectable() 데코레이터를 추가하면, NestJS는 이 클래스를 서비스로 관리할 수 있게 되는 것입니다.
* Inversion of Control 제어반전이란?
제어 반전(Inversion of Control, IoC)은 소프트웨어 디자인 원칙 중 하나로, 프로그램의 제어 흐름을 외부로부터 제어받는 방식입니다. 이는 객체가 자신의 행위를 외부에서 결정할 수 있도록 함으로써, 객체들 간의 결합도를 낮추고 유연성과 재사용성을 높이는 것을 목표로 합니다.
IoC는 의존성 주입(Dependency Injection)과 함께 많이 언급되며, 프레임워크나 컨테이너가 객체의 생성과 생명 주기를 관리하는 방식으로 구현됩니다.
NestJS는 IoC 컨테이너를 사용하여 의존성 주입을 관리합니다. 이를 통해 각 클래스가 필요한 의존성을 주입받을 수 있습니다.
1. 서비스 클래스를 정의한다.
import { Injectable } from '@nestjs/common';
@Injectable()
export class CatsService {
findAll() {
return ['cat1', 'cat2'];
}
}
2. 모듈에 프로바이더를 등록한다.
import { Module } from '@nestjs/common';
import { CatsService } from './cats.service';
@Module({
providers: [CatsService],
exports: [CatsService],
})
export class CatsModule {}
3. 컨트롤러에 서비스를 주입한다.
import { Controller, Get } from '@nestjs/common';
import { CatsService } from './cats.service';
@Controller('cats')
export class CatsController {
constructor(private readonly catsService: CatsService) {}
@Get()
findAll() {
return this.catsService.findAll();
}
}
왜 이게 의존성 주입인가?
- 의존성 주입 사용 전: 만약 의존성 주입을 사용하지 않는다면, CatsController는 CatsService를 직접 생성해야 합니다. 이는 클래스 간의 결합도를 높입니다.
export class CatsController {
private catsService: CatsService;
constructor() {
this.catsService = new CatsService();
}
@Get()
findAll() {
return this.catsService.findAll();
}
}
만약 컨트롤러에서 서비스 클래스 의존성 주입을 사용하지 않았다면, 위 코드처럼 컨트롤러에서 서비스를 다시 생성자 함수를 이용해 인스턴스를 생성해야합니다.
비교
- 의존성 주입 없이 작성 시: CatsController는 CatsService의 구체적인 구현체에 직접 의존합니다. 이는 변경에 취약하고, 테스트가 어려워집니다.
- 의존성 주입 사용 시: CatsController는 CatsService의 인스턴스를 외부에서 주입받습니다. 이를 통해 CatsController는 CatsService의 구체적인 구현체에 의존하지 않고, ICatsService라는 추상화(인터페이스)에 의존하게 됩니다.
결론 : IoC를 통해 얻게 되는 장점
- 결합도 감소: 객체가 자신이 사용할 객체를 직접 생성하지 않고, 외부에서 주입받기 때문에 클래스 간의 결합도가 낮아집니다.
- 유연성 증가: 객체를 쉽게 교체하거나 변경할 수 있습니다. 예를 들어, 테스트 시 모의 객체를 주입할 수 있게 됩니다.
용어 정리
- 의존성 주입(Dependency Injection): 클래스가 다른 클래스 또는 값에 대한 의존성을 직접 생성하지 않고, 외부에서 주입받는 디자인 패턴입니다. 이를 통해 클래스 간의 결합도를 낮추고, 테스트 용이성과 유연성을 높일 수 있습니다.
- 프로바이더(Provider): 의존성을 주입받을 수 있는 클래스 또는 값입니다. 주로 서비스 클래스가 프로바이더로 사용되곤 합니다.
- @Injectable() : @Injectable()를 붙여 클래스가 의존성 주입 컨테이너에 의해 관리될 수 있는 프로바이더임을 나타내고 싶을 때 사용합니다.
- 메타데이터 : 메타데이터는 데이터에 대한 데이터를 의미합니다. 즉, 특정 데이터에 대한 정보를 설명하거나 정의하는 데이터를 말합니다. 프로그래밍에서 메타데이터는 코드의 동작이나 구조에 관한 정보를 제공합니다.
- 제어 반전(Inversion of Control, IoC) : 소프트웨어 디자인 원칙 중 하나로, 프로그램의 제어 흐름을 외부로부터 제어받는 방식을 말합니다.
참고
공식문서 : https://docs.nestjs.com/providers
'JaveScript > NestJS' 카테고리의 다른 글
Middleware (0) | 2024.06.11 |
---|---|
@Module() (0) | 2024.06.10 |
@Body() 데코레이터 (1) | 2024.06.08 |
자동으로 JSON으로 직렬화되는 이유 (0) | 2024.06.06 |
main.ts (0) | 2024.06.04 |