์ปค์คํ ํ๋ก๋ฐ์ด๋
์์ ์ฑํฐ๋ค์์๋ Nest์์์ ์์กด์ฑ ์ฃผ์ (Dependency Injection, DI)์ ๋ค์ํ ์ธก๋ฉด๊ณผ ์ฌ์ฉ ๋ฐฉ๋ฒ์ ๋ํด ๋ค๋ฃจ์์ต๋๋ค. ๊ทธ์ค ํ๋๋ ํด๋์ค์ ์ธ์คํด์ค (๋๊ฐ ์๋น์ค ํ๋ก๋ฐ์ด๋)๋ฅผ ์ฃผ์ ํ๋ ์์ฑ์ ๊ธฐ๋ฐ ์์กด์ฑ ์ฃผ์ ์ ๋๋ค. ์์กด์ฑ ์ฃผ์ ์ด Nest์ ํต์ฌ์ ๊ทผ๋ณธ์ ์ผ๋ก ๋ด์ฅ๋์ด ์๋ค๋ ์ฌ์ค์ ์ด์ ๋ ์ด์ ๋๋์ง ์์ ๊ฒ์ ๋๋ค. ์ง๊ธ๊น์ง๋ ์ฃผ๋ก ํ๋์ ์ฃผ์ ํจํด๋ง ์ดํด๋ณด์์ง๋ง, ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ณต์กํด์ง์๋ก DI ์์คํ ์ ์ ์ฒด ๊ธฐ๋ฅ์ ํ์ฉํด์ผ ํ ํ์๊ฐ ์์ต๋๋ค. ์ด์ ์ด๋ฅผ ๋ ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
DI์ ๊ธฐ๋ณธ ์๋ฆฌ
์์กด์ฑ ์ฃผ์ ์ ์ ์ด์ ์ญ์ (Inversion of Control, IoC) ๊ธฐ๋ฒ ์ค ํ๋๋ก, ์์กด์ฑ์ ์ธ์คํด์ค ์์ฑ์ ๊ฐ๋ฐ์ ์ฝ๋๊ฐ ์๋ IoC ์ปจํ ์ด๋ (์ฌ๊ธฐ์๋ NestJS ๋ฐํ์ ์์คํ )์ ์์ํ๋ ๋ฐฉ์์ ๋๋ค. Providers ์ฑํฐ์์ ๋ณด์๋ ์์ ๋ฅผ ๋ค์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
๋จผ์ , ํ๋ก๋ฐ์ด๋๋ฅผ ์ ์ํฉ๋๋ค. @Injectable() ๋ฐ์ฝ๋ ์ดํฐ๋ CatsService ํด๋์ค๋ฅผ ํ๋ก๋ฐ์ด๋๋ก ํ์ํฉ๋๋ค.
import { Injectable } from '@nestjs/common';
import { Cat } from './interfaces/cat.interface';
@Injectable()
export class CatsService {
private readonly cats: Cat[] = [];
findAll(): Cat[] {
return this.cats;
}
}
๊ทธ๋ค์, Nest๊ฐ ํด๋น ํ๋ก๋ฐ์ด๋๋ฅผ ์ฐ๋ฆฌ์ ์ปจํธ๋กค๋ฌ ํด๋์ค์ ์ฃผ์ ํ๋๋ก ์์ฒญํฉ๋๋ค:
import { Controller, Get } from '@nestjs/common';
import { CatsService } from './cats.service';
import { Cat } from './interfaces/cat.interface';
@Controller('cats')
export class CatsController {
constructor(private catsService: CatsService) {}
@Get()
async findAll(): Promise<Cat[]> {
return this.catsService.findAll();
}
}
๋ง์ง๋ง์ผ๋ก, ํด๋น ํ๋ก๋ฐ์ด๋๋ฅผ Nest IoC ์ปจํ ์ด๋์ ๋ฑ๋กํฉ๋๋ค:
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 {}
์ด ๊ธฐ๋ฅ์ด ์๋ํ๊ธฐ ์ํด ๋ด๋ถ์ ์ผ๋ก ์ด๋ค ์ผ์ด ์ผ์ด๋๋ ๊ฑธ๊น์? ์ด ๊ณผ์ ์๋ ์ธ ๊ฐ์ง ํต์ฌ ๋จ๊ณ๊ฐ ์์ต๋๋ค:
- cats.service.ts์์ @Injectable() ๋ฐ์ฝ๋ ์ดํฐ๋ CatsService ํด๋์ค๋ฅผ Nest IoC ์ปจํ ์ด๋๊ฐ ๊ด๋ฆฌํ ์ ์๋ ํด๋์ค๋ก ์ ์ธํฉ๋๋ค.
- cats.controller.ts์์ CatsController๋ ์์ฑ์ ์ฃผ์ ์ ํตํด CatsService ํ ํฐ์ ๋ํ ์์กด์ฑ์ ์ ์ธํฉ๋๋ค.
- app.module.ts์์ CatsService ํ ํฐ์ cats.service.ts ํ์ผ์ CatsService ํด๋์ค์ ์ฐ๊ฒฐํฉ๋๋ค. ์ด ์ฐ๊ฒฐ ๊ณผ์ ์ ์๋์์ ๋ณด๊ฒ ๋ ๋ฑ๋ก (registration) ๊ณผ์ ์ ์ผํ์ ๋๋ค.
constructor(private catsService: CatsService)
Nest IoC ์ปจํ ์ด๋๊ฐ CatsController๋ฅผ ์ธ์คํด์คํํ ๋, ๋จผ์ ํด๋น ํด๋์ค์ ๋ชจ๋ ์์กด์ฑ์ ํ์ธํฉ๋๋ค. CatsService ์์กด์ฑ์ ๋ฐ๊ฒฌํ๋ฉด, ์์ 3๋จ๊ณ ๋ฑ๋ก ๊ณผ์ ์ ๋ฐ๋ผ CatsService ํ ํฐ์ ์กฐํํ์ฌ CatsService ํด๋์ค๋ฅผ ๋ฐํ๋ฐ์ต๋๋ค. ๊ธฐ๋ณธ ๋์์ธ SINGLETON ์ค์ฝํ๋ฅผ ๊ฐ์ ํ๋ฉด, Nest๋ CatsService ์ธ์คํด์ค๋ฅผ ์๋ก ์์ฑํ๊ณ ์ด๋ฅผ ์บ์ฑํ ๋ค ๋ฐํํ๊ฑฐ๋, ์ด๋ฏธ ์บ์ฑ๋ ์ธ์คํด์ค๊ฐ ์๋ค๋ฉด ๊ทธ ์ธ์คํด์ค๋ฅผ ๊ทธ๋๋ก ๋ฐํํฉ๋๋ค.
*์ด ์ค๋ช ์ ๊ฐ๋ ์ ์ฝ๊ฒ ์ ๋ฌํ๊ธฐ ์ํด ์ฝ๊ฐ ๋จ์ํ๋ ๊ฒ์ ๋๋ค. ์ค์ํ ๋ถ๋ถ ์ค ํ๋๋ ์์กด์ฑ์ ๋ถ์ํ๋ ๊ณผ์ ์ด ๋งค์ฐ ์ ๊ตํ๋ฉฐ, ์ ํ๋ฆฌ์ผ์ด์ ๋ถํธ์คํธ๋ฉ ์์ ์ ์ด๋ฃจ์ด์ง๋ค๋ ์ ์ ๋๋ค. ํต์ฌ์ ์ธ ํน์ง ์ค ํ๋๋ ์ด ์์กด์ฑ ๋ถ์ (๋๋ "์์กด์ฑ ๊ทธ๋ํ ์์ฑ")์ด ์ ์ด์ ์ด๋ผ๋ ใ ๊ฒ์ ๋๋ค. ์์ ์์์์ CatsService ์์ฒด์ ๋ ๋ค๋ฅธ ์์กด์ฑ์ด ์๋ค๋ฉด, Nest๋ ๊ทธ๊ฒ๋ค๋ ํจ๊ป ํด๊ฒฐํฉ๋๋ค. ์์กด์ฑ ๊ทธ๋ํ๋ ๋ชจ๋ ์์กด์ฑ์ด ์ฌ๋ฐ๋ฅธ ์์ (๋ณธ์ง์ ์ผ๋ก "ํํฅ์")๋ก ํด๊ฒฐ๋๋๋ก ๋ณด์ฅํฉ๋๋ค. ์ด ๋ฉ์ปค๋์ฆ ๋๋ถ์ ๊ฐ๋ฐ์๋ ๋ณต์กํ ์์กด์ฑ ๊ทธ๋ํ๋ฅผ ์ง์ ๊ด๋ฆฌํ ํ์๊ฐ ์์ต๋๋ค.
ํ์ค ํ๋ก๋ฐ์ด๋
@Module() ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ข ๋ ์์ธํ ์ดํด๋ณด๊ฒ ์ต๋๋ค. app.module์์๋ ๋ค์๊ณผ ๊ฐ์ด ์ ์ธํฉ๋๋ค:
@Module({
controllers: [CatsController],
providers: [CatsService],
})
providers ์์ฑ์ ํ๋ก๋ฐ์ด๋๋ค์ ๋ฐฐ์ด์ ๋ฐ์ต๋๋ค. ์ง๊ธ๊น์ง๋ ํด๋์ค ์ด๋ฆ ๋ชฉ๋ก์ ํตํด ํ๋ก๋ฐ์ด๋๋ฅผ ์ ๊ณตํด ์์ต๋๋ค. ์ค์ ๋ก providers: [CatsService]๋ผ๋ ๋ฌธ๋ฒ์ ๋ค์๊ณผ ๊ฐ์ ๋ ์์ ํ ๋ฌธ๋ฒ์ ์ถ์ฝ์ ๋๋ค.
providers: [
{
provide: CatsService,
useClass: CatsService,
},
];
์ด์ ์ด๋ฌํ ๋ช ์์ ์ธ ๊ตฌ์ฑ ๋ฐฉ์์ ๋ณด๋ฉด, ๋ฑ๋ก ๊ณผ์ ์ด ์ด๋ป๊ฒ ์ด๋ฃจ์ด์ง๋์ง ์ดํดํ ์ ์์ต๋๋ค. ์ฌ๊ธฐ์๋ CatsService ํ ํฐ์ CatsService ํด๋์ค์ ๋ช ํํ๊ฒ ์ฐ๊ฒฐํ๊ณ ์์ต๋๋ค. ์ถ์ฝํ ํ๊ธฐ๋ฒ์ ๋จ์ง ์ผ๋ฐ์ ์ธ ์ฌ์ฉ ์ฌ๋ก (ํ ํฐ ์ด๋ฆ๊ณผ ํด๋์ค ์ด๋ฆ์ด ๋์ผํ ๋)๋ฅผ ๊ฐ์ํํ๊ธฐ ์ํ ํธ์ ๊ธฐ๋ฅ์ผ ๋ฟ์ ๋๋ค.
์ปค์คํ ํ๋ก๋ฐ์ด๋
๊ธฐ๋ฅ ์๊ตฌ์ฌํญ์ด ํ์ค ํ๋ก๋ฐ์ด๋ (Standard providers)๋ก๋ ์ถฉ์กฑ๋์ง ์์ ๋๋ ์ด๋ป๊ฒ ํด์ผ ํ ๊น์? ๋ค์์ ๊ทธ๋ฐ ์ฌ๋ก๋ค์ ๋๋ค:
- Nest๊ฐ ํด๋์ค๋ฅผ ์ธ์คํด์คํํ๊ฑฐ๋ ์บ์ ๋ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ ๋์ , ์ง์ ์ปค์คํ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ณ ์ถ์ ๊ฒฝ์ฐ
- ๊ธฐ์กด ํด๋์ค๋ฅผ ๋ค๋ฅธ ์์กด์ฑ์์ ์ฌ์ฌ์ฉํ๊ณ ์ถ์ ๊ฒฝ์ฐ
- ํ ์คํธ๋ฅผ ์ํด ํด๋์ค๋ฅผ ๋ชจํน (mock)ํ ๋ฒ์ ์ผ๋ก ๋์ฒดํ๊ณ ์ถ์ ๊ฒฝ์ฐ
Nest๋ ์ด๋ฌํ ์ํฉ์ ์ฒ๋ฆฌํ ์ ์๋๋ก ์ปค์คํ ํ๋ก๋ฐ์ด๋ (Custom providers)๋ฅผ ์ ์ํ ์ ์๊ฒ ํด ์ค๋๋ค. ์ด๋ฅผ ์ํ ๋ค์ํ ์ ์ ๋ฐฉ๋ฒ๋ ํจ๊ป ์ ๊ณตํฉ๋๋ค. ์ด์ ๊ฐ ๋ฐฉ์์ ํจ๊ป ์ดํด๋ณด๊ฒ ์ต๋๋ค.
ํํธ
์์กด์ฑ ํด๊ฒฐ ๊ณผ์ ์์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค๋ฉด, NEST_DEBUG ํ๊ฒฝ ๋ณ์๋ฅผ ์ค์ ํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ ์์กด์ฑ ํด๊ฒฐ ๋ก๊ทธ๋ฅผ ์ถ๊ฐ๋ก ํ์ธํ ์ ์์ต๋๋ค.
๊ฐ ํ๋ก๋ฐ์ด๋: useValue
useValue ๋ฌธ๋ฒ์ ์์ ๊ฐ์ ์ฃผ์ ํ๊ฑฐ๋, ์ธ๋ถ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ Nest ์ปจํ ์ด๋์ ๋ฃ๊ฑฐ๋, ์ค์ ๊ตฌํ์ฒด๋ฅผ ๋ชฉ ๊ฐ์ฒด๋ก ๋์ฒดํ ๋ ์ ์ฉํฉ๋๋ค. ์๋ฅผ ๋ค์ด, ํ ์คํธ๋ฅผ ์ํด Nest๊ฐ ๋ชฉ์ ๋ CatsService๋ฅผ ์ฌ์ฉํ๋๋ก ๊ฐ์ ํ๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค.
import { CatsService } from './cats.service';
const mockCatsService = {
/* ๋ชฉ์
๊ตฌํ
...
*/
};
@Module({
imports: [CatsModule],
providers: [
{
provide: CatsService,
useValue: mockCatsService,
},
],
})
export class AppModule {}
์ด ์์ ์์ CatsService ํ ํฐ์ mockCatsService ๋ชฉ ๊ฐ์ฒด๋ก ํด๊ฒฐ๋ฉ๋๋ค. useValue๋ ๊ฐ์ ์๊ตฌํ๋๋ฐ, ์ด ๊ฒฝ์ฐ ๋์ฒดํ๋ ค๋ CatsService ํด๋์ค์ ๋์ผํ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ์ง ๋ฆฌํฐ๋ด ๊ฐ์ฒด์ ๋๋ค. TypeScript์ ๊ตฌ์กฐ์ ํ์ดํ (Structural Typing) ๋๋ถ์, ํธํ๋๋ ์ธํฐํ์ด์ค๋ฅผ ๊ฐ์ง ๊ฐ์ฒด๋ผ๋ฉด ์ด๋ค ๊ฒ์ด๋ ์ฌ์ฉํ ์ ์์ผ๋ฉฐ, ๋ฆฌํฐ๋ด ๊ฐ์ฒด๋ ๋ฌผ๋ก new๋ก ์์ฑํ ํด๋์ค ์ธ์คํด์ค๋ ๊ฐ๋ฅํฉ๋๋ค.
๋นํด๋์ค ๊ธฐ๋ฐ ํ๋ก๋ฐ์ด๋ ํ ํฐ
์ง๊ธ๊น์ง ์ฐ๋ฆฌ๋ ํด๋์ค ์ด๋ฆ์ ํ๋ก๋ฐ์ด๋ ํ ํฐ์ผ๋ก ์ฌ์ฉํด ์์ต๋๋ค (providers ๋ฐฐ์ด ๋ด provide ์์ฑ์ ๊ฐ). ์ด๋ ์์ฑ์ ๊ธฐ๋ฐ ์ฃผ์ ์์ ์ผ๋ฐ์ ์ผ๋ก ์ฌ์ฉ๋๋ ํจํด๊ณผ ์ผ์นํ๋ฉฐ, ์ด ๊ฒฝ์ฐ ํ ํฐ ์ญ์ ํด๋์ค ์ด๋ฆ์ ๋๋ค. (ํ ํฐ ๊ฐ๋ ์ด ์์ ํ ์ต์ํ์ง ์๋ค๋ฉด ์์ ์ค๋ช ํ DI ๊ธฐ๋ณธ ๋ด์ฉ์ ์ฐธ๊ณ ํ์ธ์.) ํ์ง๋ง ๋๋ก๋ ๋ฌธ์์ด์ด๋ ์ฌ๋ณผ์ DI ํ ํฐ์ผ๋ก ์ฌ์ฉํ๋ ์ ์ฐ์ฑ์ด ํ์ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด:
import { connection } from './connection';
@Module({
providers: [
{
provide: 'CONNECTION',
useValue: connection,
},
],
})
export class AppModule {}
์ด ์์ ์์๋ ๋ฌธ์์ด ํ ํฐ 'CONNECTION'์ ์ธ๋ถ ํ์ผ์์ ๊ฐ์ ธ์จ ๊ธฐ์กด์ ์ปค๋ฅ์ ๊ฐ์ฒด์ ์ฐ๊ฒฐํ๊ณ ์์ต๋๋ค.
์๋ฆผ
๋ฌธ์์ด ์ธ์๋ JavaScript ์ฌ๋ณผ์ด๋ TypeScript ์ด๊ฑฐํ (enum)์ ํ ํฐ ๊ฐ์ผ๋ก ์ฌ์ฉํ ์ ์์ต๋๋ค.
์์ ์ฐ๋ฆฌ๋ ํ์ค ์์ฑ์ ๊ธฐ๋ฐ ์ฃผ์ ํจํด์ ์ฌ์ฉํ์ฌ ํ๋ก๋ฐ์ด๋๋ฅผ ์ฃผ์ ํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด์์ต๋๋ค. ์ด ํจํด์์๋ ์์กด์ฑ์ ํด๋์ค ์ด๋ฆ์ผ๋ก ์ ์ธํด์ผ ํฉ๋๋ค. ๋ฐ๋ฉด, 'CONNECTION' ์ปค์คํ ํ๋ก๋ฐ์ด๋๋ ๋ฌธ์์ด ํ ํฐ์ ์ฌ์ฉํฉ๋๋ค. ์ด๋ฌํ ํ๋ก๋ฐ์ด๋๋ฅผ ์ฃผ์ ํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น์? ์ด๋ฅผ ์ํด @Inject() ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํฉ๋๋ค. ์ด ๋ฐ์ฝ๋ ์ดํฐ์์๋ ํ ํฐ์ ์ธ์๋ก ํ๋ ๋ฐ์ต๋๋ค.
@Injectable()
export class CatsRepository {
constructor(@Inject('CONNECTION') connection: Connection) {}
}
ํํธ
@Inject() ๋ฐ์ฝ๋ ์ดํฐ๋ @nestjs/common ํจํค์ง์์ ๊ฐ์ ธ์ต๋๋ค.
์ ์์ ์์๋ ์ค๋ช ์ ์ํด ๋ฌธ์์ด 'CONNECTION'์ ์ง์ ์ฌ์ฉํ์ง๋ง, ์ฝ๋์ ๊ฐ๋ ์ฑ๊ณผ ์ ์ง๋ณด์์ฑ์ ์ํด ํ ํฐ์ constants.ts์ ๊ฐ์ ๋ณ๋์ ํ์ผ์ ์ ์ํ๋ ๊ฒ์ด ๋ชจ๋ฒ ์ฌ๋ก์ ๋๋ค. ์ด๋ ์ฌ๋ณผ์ด๋ ์ด๊ฑฐํ (enum)์ ๋ณ๋ ํ์ผ์ ์ ์ํ๊ณ ํ์ํ ๋ import ํด์ ์ฌ์ฉํ๋ ๋ฐฉ์๊ณผ ๋์ผํ๊ฒ ๋ค๋ฃจ๋ ๊ฒ์ด ์ข์ต๋๋ค.
ํด๋์ค ํ๋ก๋ฐ์ด๋: useClass
useClass ๋ฌธ๋ฒ์ ํ ํฐ์ด ์ด๋ค ํด๋์ค์ ๋งคํ๋ ์ง ๋์ ์ผ๋ก ๊ฒฐ์ ํ ์ ์๊ฒ ํด ์ค๋๋ค. ์๋ฅผ ๋ค์ด, ๊ธฐ๋ณธ ๋๋ ์ถ์์ ์ธ ConfigService ํด๋์ค๊ฐ ์๊ณ , ํ์ฌ ์คํ ํ๊ฒฝ์ ๋ฐ๋ผ ์๋ก ๋ค๋ฅธ ConfigService ๊ตฌํ์ฒด๋ฅผ Nest๊ฐ ์ ๊ณตํ๋๋ก ํ๊ณ ์ถ๋ค๊ณ ๊ฐ์ ํด ๋ด ์๋ค. ์๋ ์ฝ๋๋ ๊ทธ๋ฌํ ์ ๋ต์ ๊ตฌํํ ์์์ ๋๋ค.
const configServiceProvider = {
provide: ConfigService,
useClass:
process.env.NODE_ENV === 'development'
? DevelopmentConfigService
: ProductionConfigService,
};
@Module({
providers: [configServiceProvider],
})
export class AppModule {}
์ด ์ฝ๋ ์์ ์์ ๋ช ๊ฐ์ง ์ธ๋ถ ์ฌํญ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ๋จผ์ , configServiceProvider๋ฅผ ๋ฆฌํฐ๋ด ๊ฐ์ฒด๋ก ๋จผ์ ์ ์ํ ๋ค, ์ด๋ฅผ ๋ชจ๋ ๋ฐ์ฝ๋ ์ดํฐ์ providers ์์ฑ์ ์ ๋ฌํ๊ณ ์์ต๋๋ค. ์ด๋ ๋จ์ํ ์ฝ๋ ๊ตฌ์ฑ ๋ฐฉ์์ ์ฐจ์ด์ผ ๋ฟ์ด๋ฉฐ, ๊ธฐ๋ฅ์ ์ผ๋ก๋ ์ด ์ฅ์์ ์ง๊ธ๊น์ง ์ฌ์ฉํ ๋ค๋ฅธ ์์ ๋ค๊ณผ ๋์ผํฉ๋๋ค.
๋ํ, ์ฐ๋ฆฌ๋ ConfigService ํด๋์ค ์ด๋ฆ์ ํ ํฐ์ผ๋ก ์ฌ์ฉํ์ต๋๋ค. ConfigService์ ์์กดํ๋ ํด๋์ค๊ฐ ์์ ๊ฒฝ์ฐ, Nest๋ ๋ฑ๋ก๋ ํด๋์ค (DevelopmentConfigService ๋๋ ProductionConfigService)์ ์ธ์คํด์ค๋ฅผ ์ฃผ์ ํฉ๋๋ค. ์ด๋ ๋ค๋ฅธ ๊ณณ์ ์ ์ธ๋ ๊ธฐ๋ณธ ๊ตฌํ (@Injectable() ๋ฐ์ฝ๋ ์ดํฐ๋ก ์ ์ธ๋ ConfigService ๋ฑ)์ ๋ฎ์ด์ฐ๊ฒ ๋ฉ๋๋ค.
ํฉํ ๋ฆฌ ํ๋ก๋ฐ์ด๋: useFactory
useFactory ๋ฌธ๋ฒ์ ํ๋ก๋ฐ์ด๋๋ฅผ ๋์ ์ผ๋ก ์์ฑํ ์ ์๊ฒ ํด ์ค๋๋ค. ์ค์ ํ๋ก๋ฐ์ด๋๋ ํฉํ ๋ฆฌ ํจ์๊ฐ ๋ฐํํ๋ ๊ฐ์ ์ํด ์ ๊ณต๋ฉ๋๋ค. ์ด ํฉํ ๋ฆฌ ํจ์๋ ๋จ์ํ ์๋ ์๊ณ ๋ณต์กํ ์๋ ์์ต๋๋ค. ๋จ์ํ ๊ฒฝ์ฐ์๋ ๋ค๋ฅธ ํ๋ก๋ฐ์ด๋์ ์์กดํ์ง ์์ ์ ์๊ณ , ๋ณต์กํ ๊ฒฝ์ฐ์๋ ๊ฒฐ๊ณผ๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํด ๋ค๋ฅธ ํ๋ก๋ฐ์ด๋๋ฅผ ์ฃผ์ ๋ฐ์ ์๋ ์์ต๋๋ค. ์ด๋ฌํ ๋ณต์กํ ๊ฒฝ์ฐ๋ฅผ ์ง์ํ๊ธฐ ์ํด useFactory๋ ๋ค์ ๋ ๊ฐ์ง ๋ฉ์ปค๋์ฆ์ ํจ๊ป ์ ๊ณตํฉ๋๋ค:
- ํฉํ ๋ฆฌ ํจ์๋ (์ ํ์ ์ผ๋ก) ์ธ์๋ฅผ ๋ฐ์ ์ ์์ต๋๋ค.
- inject ์์ฑ์ Nest๊ฐ ์ธ์คํด์ค๋ฅผ ์ฃผ์ ํด์ผ ํ ํ๋ก๋ฐ์ด๋ ๋ชฉ๋ก์ ๋ฐฐ์ด๋ก ๋ฐ์ต๋๋ค. Nest๋ ์ด ๋ชฉ๋ก์ ๊ฐ ํ๋ก๋ฐ์ด๋๋ฅผ ํด์ํด ํฉํ ๋ฆฌ ํจ์์ ์ธ์๋ก ์ ๋ฌํฉ๋๋ค. ์ด๋, ์์๊ฐ ์ค์ํ๋ฉฐ, ํ์์ ๊ฐ ํญ๋ชฉ์ ์ ํ์ ์ผ๋ก ์ง์ ํ ์๋ ์์ต๋๋ค.
์๋ ์์ ๋ ์ด๋ฌํ ๋์์ ์ ๋ณด์ฌ์ค๋๋ค.
const connectionProvider = {
provide: 'CONNECTION',
useFactory: (optionsProvider: MyOptionsProvider, optionalProvider?: string) => {
const options = optionsProvider.get();
return new DatabaseConnection(options);
},
inject: [MyOptionsProvider, { token: 'SomeOptionalProvider', optional: true }],
// \______________/ \__________________/
// ์ด ํ๋ก๋ฐ์ด๋๋ ์ด ํ ํฐ์ ๊ฐ์ง ํ๋ก๋ฐ์ด๋๋
// ํ์์
๋๋ค. `undefined`๋ก ํด๊ฒฐ๋ ์ ์์ต๋๋ค.
};
@Module({
providers: [
connectionProvider,
MyOptionsProvider, // ํด๋์ค ๊ธฐ๋ฐ ํ๋ก๋ฐ์ด๋
// { provide: 'SomeOptionalProvider', useValue: 'anything' }, // ์ ํ์ ํ๋ก๋ฐ์ด๋ ์์
],
})
export class AppModule {}
๋ณ์นญ ํ๋ก๋ฐ์ด๋: useExisting
useExisting ๋ฌธ๋ฒ์ ๊ธฐ์กด ํ๋ก๋ฐ์ด๋์ ๋ํ ๋ณ์นญ (alias)์ ์์ฑํ ์ ์๊ฒ ํด ์ค๋๋ค. ์ด๋ก์จ ํ๋์ ํ๋ก๋ฐ์ด๋๋ฅผ ๋ ๊ฐ ์ด์์ ํ ํฐ์ผ๋ก ์ ๊ทผํ ์ ์๊ฒ ํด ์ค๋๋ค. ์๋ ์์ ์์๋ ๋ฌธ์์ด ๊ธฐ๋ฐ ํ ํฐ 'AliasedLoggerService'๊ฐ ํด๋์ค ๊ธฐ๋ฐ ํ ํฐ LoggerService์ ๋ณ์นญ ์ญํ ์ ํฉ๋๋ค. ์๋ฅผ ๋ค์ด, 'AliasedLoggerService'์ LoggerService ๊ฐ๊ฐ์ ์์กด์ฑ์ผ๋ก ๊ฐ์ง ๋ ์ปดํฌ๋ํธ๊ฐ ์๋ค๊ณ ๊ฐ์ ํ๋ฉด, ๋ ํ ํฐ์ด ๋ชจ๋ SINGLETON ์ค์ฝํ๋ก ์ง์ ๋ ๊ฒฝ์ฐ ๋์ผํ ์ธ์คํด์ค๋ก ํด๊ฒฐ๋ฉ๋๋ค.
@Injectable()
class LoggerService {
/* ๊ตฌํ ์์ธ */
}
const loggerAliasProvider = {
provide: 'AliasedLoggerService',
useExisting: LoggerService,
};
@Module({
providers: [LoggerService, loggerAliasProvider],
})
export class AppModule {}
๋น์๋น์ค ๊ธฐ๋ฐ ํ๋ก๋ฐ์ด๋
ํ๋ก๋ฐ์ด๋๋ ์ฃผ๋ก ์๋น์ค๋ฅผ ์ ๊ณตํ์ง๋ง, ๊ทธ ์ฉ๋์ ์ ํ์ ์์ต๋๋ค. ํ๋ก๋ฐ์ด๋๋ ์ด๋ค ๊ฐ์ด๋ ์ ๊ณตํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์๋์ ๊ฐ์ด ํ์ฌ ํ๊ฒฝ์ ๋ฐ๋ผ ๊ตฌ์ฑ ๊ฐ์ฒด ๋ฐฐ์ด์ ์ ๊ณตํ๋ ํ๋ก๋ฐ์ด๋๋ ๋ง๋ค ์ ์์ต๋๋ค.
const configFactory = {
provide: 'CONFIG',
useFactory: () => {
return process.env.NODE_ENV === 'development' ? devConfig : prodConfig;
},
};
@Module({
providers: [configFactory],
})
export class AppModule {}
์ปค์คํ ํ๋ก๋ฐ์ด๋ ๋ด๋ณด๋ด๊ธฐ
๋ค๋ฅธ ํ๋ก๋ฐ์ด๋์ ๋ง์ฐฌ๊ฐ์ง๋ก, ์ปค์คํ ํ๋ก๋ฐ์ด๋๋ ์ ์๋ ๋ชจ๋ ๋ด๋ถ์ ํ์ ๋ ๋ฒ์ (scope)๋ฅผ ๊ฐ์ง๋๋ค. ์ด๋ฅผ ๋ค๋ฅธ ๋ชจ๋์์๋ ์ฌ์ฉํ ์ ์๋๋ก ํ๋ ค๋ฉด export ํด์ผ ํฉ๋๋ค. ์ปค์คํ ํ๋ก๋ฐ์ด๋๋ฅผ export ํ๋ ค๋ฉด ํ ํฐ ๋๋ ์ ์ฒด ํ๋ก๋ฐ์ด๋ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
๋ค์ ์์ ๋ ํ ํฐ์ ์ฌ์ฉํ์ฌ export ํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
const connectionFactory = {
provide: 'CONNECTION',
useFactory: (optionsProvider: OptionsProvider) => {
const options = optionsProvider.get();
return new DatabaseConnection(options);
},
inject: [OptionsProvider],
};
@Module({
providers: [connectionFactory],
exports: ['CONNECTION'],
})
export class AppModule {}
๋๋, ์ ์ฒด ํ๋ก๋ฐ์ด๋ ๊ฐ์ฒด๋ฅผ ์ฌ์ฉํ์ฌ export ํ ์๋ ์์ต๋๋ค:
const connectionFactory = {
provide: 'CONNECTION',
useFactory: (optionsProvider: OptionsProvider) => {
const options = optionsProvider.get();
return new DatabaseConnection(options);
},
inject: [OptionsProvider],
};
@Module({
providers: [connectionFactory],
exports: [connectionFactory],
})
export class AppModule {}
๋น๋๊ธฐ ํ๋ก๋ฐ์ด๋
์ ํ๋ฆฌ์ผ์ด์ ์ด ์์๋๊ธฐ ์ ์ ํ๋ ์ด์์ ๋น๋๊ธฐ ์์ ์ด ์๋ฃ๋ ๋๊น์ง ์์์ ์ง์ฐ์์ผ์ผ ํ๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ด ์๋ฃ๋๊ธฐ ์ ๊น์ง๋ ์์ฒญ์ ๋ฐ์ง ์๋๋ก ํ๊ณ ์ถ์ ์ ์์ต๋๋ค. ์ด๋ฌํ ์๊ตฌ๋ ๋น๋๊ธฐ ํ๋ก๋ฐ์ด๋ (Asynchronous providers)๋ฅผ ์ฌ์ฉํ์ฌ ํด๊ฒฐํ ์ ์์ต๋๋ค.
์ด๋ฅผ ์ํ ๋ฌธ๋ฒ์ useFactory ๋ฌธ๋ฒ๊ณผ ํจ๊ป async/await์ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค. ํฉํ ๋ฆฌ ํจ์๋ Promise๋ฅผ ๋ฐํํ๋ฉฐ, ๊ทธ ์์์ ๋น๋๊ธฐ ์์ ์ await ํ ์ ์์ต๋๋ค. Nest๋ ํด๋น ํ๋ก๋ฐ์ด๋์ ์์กดํ๋ ์ด๋ค ํด๋์ค๋ ์ธ์คํด์คํํ๊ธฐ ์ ์ ํด๋น Promise๊ฐ ํด๊ฒฐ๋ ๋๊น์ง ๋๊ธฐํฉ๋๋ค.
{
provide: 'ASYNC_CONNECTION',
useFactory: async () => {
const connection = await createConnection(options);
return connection;
},
}
ํํธ
์ปค์คํ ํ๋ก๋ฐ์ด๋ ๋ฌธ๋ฒ์ ๋ํด ๋ ์์๋ณด๋ ค๋ฉด ์ฌ๊ธฐ๋ฅผ ์ฐธ๊ณ ํ์ธ์.
์ฃผ์
๋น๋๊ธฐ ํ๋ก๋ฐ์ด๋๋ ๋ค๋ฅธ ์ผ๋ฐ ํ๋ก๋ฐ์ด๋๋ค๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ํ ํฐ์ ํตํด ๋ค๋ฅธ ์ปดํฌ๋ํธ์ ์ฃผ์ ๋ฉ๋๋ค. ์ ์์ ์์์ฒ๋ผ, ๋ค์๊ณผ ๊ฐ์ด ์ฃผ์ ํ ์ ์์ต๋๋ค: @Inject('ASYNC_CONNECTION')
์์
TypeORM ๋ ์ํผ์๋ ๋น๋๊ธฐ ํ๋ก๋ฐ์ด๋๋ฅผ ํ์ฉํ ๋ ์ค์ง์ ์ธ ์์ ๊ฐ ํฌํจ๋์ด ์์ต๋๋ค.
Reference
'๐ ๊ณต์ ๋ฌธ์ ๋ฒ์ญ > Nest.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Nest.js] Fundamentals - Circular dependency, Module reference (0) | 2025.07.19 |
---|---|
[Nest.js] Fundamentals - Dynamic modules, Injection scopes (0) | 2025.07.16 |
[Nest.js] Overview - Interceptors, Custom decorators (0) | 2025.07.13 |
[Nest.js] Overview - Pipes, Guards (0) | 2025.07.08 |
[Nest.js] Overview - Middleware, Exception filters (2) | 2025.07.07 |