Provider란 무엇인가?
NestJS에서 Provider는 애플리케이션 내에서 특정 기능을 캡슐화하여 제공하는 클래스를 의미합니다.
일반적으로 Service, Repository, Factory, Helper 등이 포함됩니다.
이들은 @Injectable() 데코레이터가 달려 있으며, NestJS의 의존성 주입 컨테이너에 등록됩니다. 이를 통해 Provider는 애플리케이션의 다른 곳에서 쉽게 참조되고 재사용될 수 있습니다.
@Injectable() 데코레이터
@Injectable() 데코레이터는 클래스에 달아 해당 클래스를 Provider로 등록합니다.
이 데코레이터를 붙임으로써 NestJS는 해당 클래스를 DI컨테이너에 추가하고, 필요한 곳에서 주입할 수 있게 합니다.
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): string {
return 'Hello World!';
}
}
위의 AppService는 @Injectable()로 Provider로 등록되어, 다른 클래스에서 주입되어 사용될 수 있습니다.
Provider의 사용 목적과 의존성 주입의 역할
서비스를 만들다보면 의존성 문제에 대한 처리가 필요합니다. Provider는 캡슐화를 통해서 의존성 문제 뿐만 아니라, Mocking을 통한 테스트에도 용이합니다.
- 역할 분리와 재사용성: Provider는 특정 기능을 캡슐화하여 모듈화하기 때문에, 다른 클래스에 주입하여 반복되는 로직을 줄이고 코드의 재사용성을 높일 수 있습니다.
- 의존성 관리: NestJS는 의존성을 자동으로 주입하는 DI 컨테이너를 제공하여, Provider 간의 종속성을 관리하고, 의존성이 복잡한 애플리케이션에서도 명확하게 관리할 수 있습니다.
- 테스트 용이성: Provider는 주입된 의존성을 쉽게 목(Mock) 처리할 수 있어, 유닛 테스트를 작성하기에 용이합니다. 서비스 또는 리포지토리를 DI를 통해 주입받아, 테스트 환경에서 다양한 시나리오를 시뮬레이션할 수 있습니다.
Provider를 사용하는 예: AppService와 AppController
아래 예시는 AppService를 Provider로 설정하고, 이를 AppController에서 주입받아 사용하는 구조입니다.
AppService (서비스)
typescript
코드 복사
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getGreeting(): string {
return 'Hello, NestJS!';
}
}
AppController (컨트롤러)
typescript
코드 복사
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {} // AppService 주입
@Get()
getGreeting(): string {
return this.appService.getGreeting(); // 주입된 AppService 사용
}
}
- AppService는 @Injectable() 데코레이터로 Provider가 되었으며, AppController는 생성자에 AppService를 주입받아 사용합니다.
- AppController는 appService.getGreeting() 메서드를 통해 서비스 기능을 호출합니다. 이처럼 의존성을 주입하여 컨트롤러와 서비스의 역할을 분리하고, 테스트나 재사용성이 향상됩니다.
Dependency Injection
`provider의 주요 아이디어는 dependencies를 inject할 수 있다는 것이다.`는 "dependencies를 inject한다"와 "인스턴스화한다"는 다른 말입니다.
의존성 주입은 필요한 객체(의존성)를 외부에서 주입하여 전달하는 방식을 의미합니다. 즉, 클래스가 필요한 객체를 스스로 생성하지 않고, 외부에서 전달받아 사용하는 방식입니다. 이를 통해 의존성 문제를 해결할 수 있습니다.
NestJS에서는 DI 컨테이너가 특정 클래스(예: AppService)를 주입해야 할 때, 해당 클래스의 인스턴스를 생성하고 이를 주입하여 다른 클래스에서 사용할 수 있게 합니다.
예를 들어, AppController가 AppService에 의존하고 있다면, NestJS의 DI 컨테이너는 AppController 생성 시 AppService 인스턴스를 주입해줍니다.
의존성 주입(Dependency Injection)은 필요한 객체를 주입하는 과정 전체를 의미하고, 인스턴스화는 이 과정에서 객체가 필요한 경우 새롭게 인스턴스를 생성하는 단계 중 하나입니다.
추가적으로 알아두면 좋은 내용: DI 컨테이너와 프로바이더의 수명 주기
NestJS에서 Provider의 생명주기는 애플리케이션의 DI 컨테이너가 관리합니다. DI 컨테이너는 프로바이더의 생성과 소멸을 관리하며, 싱글톤 패턴을 따르기 때문에 같은 프로바이더가 여러 곳에서 사용되더라도 하나의 인스턴스로 공유됩니다. 이를 통해 애플리케이션의 메모리 사용이 최적화됩니다.
예외 상황: 요청 스코프 및 트랜지언트 스코프
특정한 경우, 예를 들어 요청마다 인스턴스가 달라야 하는 경우에는 Provider에 스코프를 설정할 수도 있습니다:
- REQUEST 스코프: 각 HTTP 요청마다 새로운 인스턴스를 생성합니다.
- TRANSIENT 스코프: 프로바이더가 주입될 때마다 새로운 인스턴스를 생성합니다.
이처럼 NestJS의 Provider는 모듈화, 의존성 관리, 테스트 용이성 등을 개선하여 백엔드 애플리케이션의 효율적이고 유지보수 가능한 코드를 작성하는 데 도움을 줍니다. Spring에서의 의존성 주입과 유사하게 이해할 수 있으며, @Injectable()을 통해 쉽게 사용 가능합니다.
'Dev Framework > NestJS' 카테고리의 다른 글
[NestJS] enableCors( ) (1) | 2024.11.21 |
---|---|
[NestJS][TypeORM] Data Mapper Pattern (0) | 2024.11.19 |
[NestJS] pipe (3) | 2024.11.18 |
[NestJS][TypeORM] Activate Record Pattern (0) | 2024.11.18 |