2023. 5. 31. 21:17ㆍ개발 문서 번역/NestJS
이 포스팅은 「NestJS 기초실무 가이드 : 강력하고 쉬운 Node.js 웹 프레임워크로 웹사이트 만들기」
(서명: NestJS 基礎必學實務指南:使用強大且易擴展的 Node.js 框架打造網頁應用程式)
책이 출간되었습니다.
Custom Provider 내보내기
공유 모듈을 소개할 때 exports를 통해 Provider를 내보낼 수 있다고 언급 했었습니다.
그렇다면 Provider를 어떻게 내보낼 수 있을까요?
테스트를 위해 먼저 HandsomeModule을 생성해보도록 하겠습니다.
$ nest generate module handsome
Custom Provider를 변수에 저장한 다음 해당 변수를 providers와 exports에 넣어줍니다.
import { Module } from '@nestjs/common';
const HANDSOME_WOO = {
provide: 'HANDSOME_MAN',
useValue: {
name: 'WOO'
}
};
@Module({
providers: [
HANDSOME_WOO
],
exports: [
HANDSOME_WOO
]
})
export class HandsomeModule {}
이제 AppModule에서 HandsomeModule을 불러와보겠습니다.
아래는 app.module.ts의 예제입니다.
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { HandsomeModule } from './handsome/handsome.module';
@Module({
imports: [HandsomeModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
app.controller.ts를 수정하여 결과를 확인하면 터미널에는 아래의 값이 출력됩니다.
{ name: 'WOO' }
비동기 Provider (Asynchronous Provider)
가끔은 Provider를 생성하기 위해선 비동기 작업을 기다려야 할 때도 있습니다.
ex: 데이터베이스에 연결해야할 때, Nest App은 해당 Provider가 생성된 후에야 시작됩니다.
이의 경우 위의 hansome.module.ts을 아래와 같이 수정하면 됩니다.
import { Module } from '@nestjs/common';
const HANDSOME_WOO = {
provide: 'HANDSOME_MAN',
useFactory: async () => {
const getWOO = new Promise(resolve => {
setTimeout(() => resolve({ name: 'WOO' }), 2000);
});
const WOO = await getWOO;
return WOO;
}
};
@Module({
providers: [
HANDSOME_WOO
],
exports: [
HANDSOME_WOO
]
})
export class HandsomeModule {}
2초 후 터미널에는 아래와 같은 결과가 출력됩니다.
{ name: 'WOO' }
선택적 Provider (Optional providers)
가끔은 Provider를 제공하지 않고도 프로바이더를 주입해야 할 경우가 생깁니다.
(반드시 해결될 필요가 없는 종속성이 있을 때가 있습니다.)
이런 경우에는 앱이 시작될 때 Provider를 찾을 수 없어 오류가 발생하는데요.
이런 상황에는 어떻게 대처해야 할까요?
주입 위치에 @Optional 데코레이터를 추가하여 기본값을 설정하는 것이 일반적인 방법입니다.
아래의 예제에서는 위의 방법을 인용하여 HandsomeModule을 불러오지 않겠습니다.
아래는 app.module.ts의 예제입니다.
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
다음으로 app.controller.ts의 내용을 수정할텐데요. HANDSOME_MAN에 기본값을 할당합니다.
import { Controller, Get, Inject, Optional } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(
private readonly appService: AppService,
@Optional() @Inject('HANDSOME_MAN') private readonly handsomeMan = { name: '' }
) {
console.log(this.handsomeMan);
}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
터미널에 아래와 같은 결과가 표시됩니다.
{ name: '' }
*추가적으로 알아두면 좋은 사항
속성 기반 주입
속성 기반 주입이란
//propertyBase.catparentService.ts
export class catParentService{
constructor(private readonly testServiceA: TestServiceA){
}
testHello(): string{
return "hello world"
}
parentTest(): string{
return this.testServiceA.testHello();
}
}
// propertyBase.catchildService.ts
@Injectable()
export class catChildService extends catParentService{
constructor(private readonly tsA: TestServiceA){
super(tsA)
}
testHello(): string{
return this.parentTest()
}
}
// propertyBase.testServiceA.ts
@Injectable()
export class TestServiceA{
testHello(){
return "hello Test A";
}
}
위의 코드 catChildService에서 super()를 상속하여 TestServiceA의 인스턴스를 전달해줄 수 있습니다.
이때 /cat/propertyBase로 요청시 "test Hello A" 라는 문자열을 응답으로 받을 수 있습니다.
하지만 이런 경우가 발생할 때마다 super를 사용하는건 엄청 불편한 일이기 때문에 이때는
사용하던 생성자 기반의 주입 방식이 아닌 속성 기반 주입을 사용할 수 있습니다.
방법은 매우 간단한데
catParentService의 constructor 부분을 @Inject()로 대체하면 됩니다.
//propertyBase.catparentService.ts
export class catParentService{
@Inject(TestServiceA) private readonly testServiceA: TestServiceA;
testHello(): string {
return "hello world"
}
parentTest(): string {
return this.testServiceA.testHello();
}
}
//propertyBase.catchildService.ts
@Injectable()
export class catChildService extends catParentService {
testHello(): string{
return this.parentTest()
}
}
//propertyBase.testService.ts
@Injectable()
export class TestServiceA {
testHello(){
return "hello Test A"
}
}
이제 /cat/propertyBase로 GET 요청을 보내면 "hello Test A" 라는 문구를 받아올 수 있게 됩니다.
마치며
오늘은 Provider에 대한 몇가지 기술들을 다루었습니다.
아래는 오늘 배운 내용의 정리본입니다.
1. Custom Provider는 프로바이더 객체 []를 변수에 할당하여 내보내기가 가능합니다.
2. Provider는 비동기 생성을 지원하며 Provider가 완전히 생성되기 전까지 Nest App은 시작되지 않습니다.
3. Provider가 필수 항목이 아닌 경우, @Optional 데코레이터를 추가하여 기본값을 설정해야 합니다.
Nest의 가장 중요한 3가지 개념을 배워보았습니다.
내일부터는 Nest의 다른 기능을 소개하도록 하겠습니다!
'개발 문서 번역 > NestJS' 카테고리의 다른 글
NestJS 帶你飛! 시리즈 번역 09# Pipe (상) (0) | 2023.06.02 |
---|---|
NestJS 帶你飛! 시리즈 번역 08# Exception & Exception filters (0) | 2023.06.01 |
NestJS 帶你飛! 시리즈 번역 06# Provider (상) (0) | 2023.05.31 |
NestJS 帶你飛! 시리즈 번역 05# Module (0) | 2023.05.30 |
NestJS 帶你飛! 시리즈 번역 04# Controller (하) (0) | 2023.05.30 |