Prodiver는 Nest의 가장 핵심적인 개념이다.
Service, Repository, Factory, Hepler와 같은 Nest의 기본 클래스들이 모두 Provider로 다루어진다.
Provider의 핵심적인 개념은 각각의 형태로 관계를 가지고, 의존성에 맞도록 주입되는 것이다.
이런 객체들을 연결해주는 것은 Nest runtime system의 큰 과제이다.
이전 장에서 CatsController를 만들었던 것을 생각해보자.
컨트롤러는 단순히 Http 요청을 처리하고, 복잡한 작업은 Provider에게 위임해야 한다.
여기서 Provider는 Nest에서 providers로 선언된 자바스크립트 클래스를 말한다.
- Services
이번에는 예시로 CatsService를 만들어보자.
해당 서비스는 데이터의 저장과 조회를 담당하며, CatsController에서 사용할 예정이다.
이런 애플리케이션 로직을 다루기 때문에, provider 모듈에서 다뤄지게 되는 것이다.
import { Cat } from './interfaces/cat.interface';
import { Injectable } from '@nestjs/common';
@Injectable()
export class CatsService {
private readonly cats: Cat[] = [];
create(cat: Cat) {
this.cats.push(cat);
}
findAll(): Cat[] {
return this.cats;
}
}
CatsService는 하나의 멤버 변수와 두개의 메서드를 가지고 있다.
여기서 가장 중요한 포인트는 @Injectable() 데코레이터이다.
해당 데코레이터는 클래스에 메타데이터를 추가해서, CatsService가 Nest의 IoC 컨테이너에 의해 관리될 수 있도록 한다.
이 CatsService는 클래스의 생성자를 통해 주입되게 된다.
import {
Controller,
Body,
Get,
Post,
Put,
Delete,
Param,
Query,
} from '@nestjs/common';
import { CreateCatDto } from './dto/create-cat.dto';
import { CatsService } from './cats.service';
@Controller('/cats')
export class CatsController {
constructor(private readonly catService: CatsService) {}
@Post()
create(@Body() createCatDto: CreateCatDto): string {
console.log(createCatDto);
return 'This action adds a new cat';
}
@Get()
findAll(@Query('age') age: number, @Query('breed') breed: string): string {
return `This action returns all cats filtered by age: ${age} and breed: ${breed}`;
}
@Get(':id')
findOne(@Param('id') id: string) {
return `This action returns a #${id} cat`;
}
@Put(':id')
update(@Param('id') id: string, @Body() createCatDto: CreateCatDto) {
return `This action updates a #${id} cat ${createCatDto.name}`;
}
@Delete(':id')
remove(@Param('id') id: string) {
return `This action removes a #${id} cat`;
}
}
- Dependency injection
Nest는 의존성 주입이라고 많이 알려진 강력한 디자인 패턴을 통해 빌드된다.
이것에 대해서는 Angular의 문서를 참고하면 좋다고 한다.
Angular
The web development framework for building modern apps.
angular.dev
TypeScript를 활용하기에 Nest에서는 타입을 통해 이러한 의존성들이 관리될 수 있다.
나중에 저 Angular의 문서를 읽고서도 블로그를 써보도록 해야겠다.
- Scopes
provider는 생명주기를 가지게 되며, 그 생명주기는 보통 애플리케이션의 생명주기와 동행한다.
애플리케이션이 부트스트랩되면, 모든 의존성들은 해결되어야 할 것이며 모든 provider가 instantiated되어야 한다는 것이다.
비슷하게 애플리케이션이 종료된다면, 이런 Provider는 모두 같이 종료되어야 한다.
그러나 이런 Provider를 범위를 지정해서 넣도록 할 수 있다.
그럴 때는 이 생명 주기가 애플리케이션이 되는 것이 아니라, 특정 요청에 대해 묶이게 되는 것이다.
나중에 Injection Scope에서 더 자세히 알아보도록 하자.
- Optional providers
가끔은 항상 해결할 필요가 없는 의존성이 있을 수도 있다.
예를 들어, 특별한 구성 요소에 의존할 수 있지만, 해당 객체가 제공되지 않는 경우 기본값을 사용하도록 할 수 있다.
이런 경우 해당 의존성은 선택적으로 간주되며, 설정을 따로 해주지 않더라도 에러가 발생해서는 안된다.
공급자를 선택적으로 표시하기 위해서는, 생성자에 @Optional() 데코레이터를 사용하면 된다.
import { Injectable, Optional, Inject } from '@nestjs/common';
@Injectable()
export class HttpService<T> {
constructor(@Optional() @Inject('HTTP_OPTIONS') private httpClient: T) {}
}
여기 예시에서는 custom provider를 사용하기에 HTTP_OPTIONS라는 커스텀 토큰을 포함하고 있다.
여기서는 의존성을 생성자의 클래스로 지정했다.
나중에 해당 챕터에서 더 자세히 알아보자.
- Provider registration
이번에 CatsService라는 Provider와 CatsController라는 Consumer를 정의했었다.
우리는 이것들을 Nest에 등록해서 주입과정에서 다룰 수 있도록 해야한다.
등록은 app.module.ts를 수정해서 진행해야 하며, providers에 service를 넣어주면 된다.
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 {}
'Node > Nest 공식문서' 카테고리의 다른 글
| Modules (0) | 2025.08.23 |
|---|---|
| Controllers (0) | 2025.08.20 |
| First steps (2) | 2025.08.18 |
| Introduction (4) | 2025.08.18 |