ํ๋ก๋ฐ์ด๋ (Providers)
Nest์์ ํ๋ก๋ฐ์ด๋ (Provider)๋ ํต์ฌ ๊ฐ๋ ์ ๋๋ค. ์๋น์ค, ๋ฆฌํฌ์งํฐ๋ฆฌ, ํฉํ ๋ฆฌ, ํฌํผ์ ๊ฐ์ ๊ธฐ๋ณธ Nest ํด๋์ค ๋๋ถ๋ถ์ ํ๋ก๋ฐ์ด๋๋ก ์ทจ๊ธ๋ ์ ์์ต๋๋ค. ํ๋ก๋ฐ์ด๋์ ํต์ฌ ์์ด๋์ด๋ ์์กด์ฑ์ผ๋ก ์ฃผ์ ๋ ์ ์๋ค๋ ์ ์ด๋ฉฐ, ์ด๋ฅผ ํตํด ๊ฐ์ฒด๋ค ๊ฐ์ ๋ค์ํ ๊ด๊ณ๋ฅผ ํ์ฑํ ์ ์์ต๋๋ค. ์ด๋ฌํ ๊ฐ์ฒด๋ค์ ์ฐ๊ฒฐ(wiring) ํ๋ ์์ ์ ๋๋ถ๋ถ Nest์ ๋ฐํ์ ์์คํ ์ด ์๋์ผ๋ก ์ฒ๋ฆฌํฉ๋๋ค.
์ด์ ์ฅ์์๋ ๊ฐ๋จํ CatsController๋ฅผ ๋ง๋ค์์ต๋๋ค. ์ปจํธ๋กค๋ฌ๋ HTTP ์์ฒญ์ ์ฒ๋ฆฌํ๊ณ , ๋ ๋ณต์กํ ์์ ์ ํ๋ก๋ฐ์ด๋์๊ฒ ์์ํ๋ ๊ฒ์ด ์ข์ต๋๋ค. ํ๋ก๋ฐ์ด๋๋ NestJS ๋ชจ๋์์ ํ๋ก๋ฐ์ด๋๋ก ์ ์ธ๋ ์ผ๋ฐ JavaScript ํด๋์ค์ ๋๋ค. ์์ธํ ๋ด์ฉ์ ๋ชจ๋ (Modules) ์ฅ์ ์ฐธ๊ณ ํ์ธ์.
ํํธ
Nest๋ ๊ฐ์ฒด ์งํฅ ๋ฐฉ์์ผ๋ก ์์กด์ฑ์ ์ค๊ณํ๊ณ ๊ตฌ์ฑํ ์ ์๋๋ก ํด์ฃผ๊ธฐ ๋๋ฌธ์, SOLID ์์น์ ๋ฐ๋ฅด๋ ๊ฒ์ ๊ฐ๋ ฅํ ๊ถ์ฅํฉ๋๋ค.
์๋น์ค
์ด์ ๊ฐ๋จํ CatsService๋ฅผ ๋ง๋ค์ด ๋ณด๊ฒ ์ต๋๋ค. ์ด ์๋น์ค๋ ๋ฐ์ดํฐ์ ์ ์ฅ ๋ฐ ์กฐํ๋ฅผ ๋ด๋นํ๋ฉฐ, CatsController์์ ์ฌ์ฉ๋ ๊ฒ์ ๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ก์ง์ ๊ด๋ฆฌํ๋ ์ญํ ์ ํ๊ธฐ ๋๋ฌธ์, ํ๋ก๋ฐ์ด๋๋ก ์ ์ํ๊ธฐ์ ์ ํฉํ ๋์์ ๋๋ค.
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;
}
}
ํํธ
CLI๋ฅผ ์ฌ์ฉํ์ฌ ์๋น์ค๋ฅผ ์์ฑํ๋ ค๋ฉด, ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํ๋ฉด ๋ฉ๋๋ค: nest g service cats
CatsService๋ ํ๋์ ์์ฑ๊ณผ ๋ ๊ฐ์ ๋ฉ์๋๋ฅผ ๊ฐ์ง ๊ธฐ๋ณธ ํด๋์ค์ ๋๋ค. ์ฌ๊ธฐ์ ํต์ฌ์ @Injectable() ๋ฐ์ฝ๋ ์ดํฐ์ ๋๋ค. ์ด ๋ฐ์ฝ๋ ์ดํฐ๋ ํด๋์ค์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๋ถ์ฌํ์ฌ, Nest์ IoC ์ปจํ ์ด๋๊ฐ ์ด ํด๋์ค๋ฅผ ์์กด์ฑ ์ฃผ์ ์ด ๊ฐ๋ฅํ ๊ด๋ฆฌ ๋์์ผ๋ก ์ธ์ํ๋๋ก ํฉ๋๋ค.
๋ํ ์ด ์์ ๋ Cat์ด๋ผ๋ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ฉฐ, ์ด๋ ๋ค์๊ณผ ๊ฐ์ ํํ์ผ ๊ฐ๋ฅ์ฑ์ด ๋์ต๋๋ค:
export interface Cat {
name: string;
age: number;
breed: string;
}
์ด์ ๊ณ ์์ด ์ ๋ณด๋ฅผ ์กฐํํ ์ ์๋ ์๋น์ค ํด๋์ค๊ฐ ์ค๋น๋์์ผ๋, ์ด๋ฅผ CatsController ์์์ ์ฌ์ฉํด ๋ณด๊ฒ ์ต๋๋ค:
import { Controller, Get, Post, Body } from '@nestjs/common';
import { CreateCatDto } from './dto/create-cat.dto';
import { CatsService } from './cats.service';
import { Cat } from './interfaces/cat.interface';
@Controller('cats')
export class CatsController {
constructor(private catsService: CatsService) {}
@Post()
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
@Get()
async findAll(): Promise<Cat[]> {
return this.catsService.findAll();
}
}
CatsService๋ ํด๋์ค ์์ฑ์๋ฅผ ํตํด ์ฃผ์ ๋ฉ๋๋ค. ์ฌ๊ธฐ์ ์ฃผ๋ชฉํ ์ ์ private ํค์๋์ ์ฌ์ฉ์ ๋๋ค. ์ด ์ถ์ฝํ ๋ฌธ๋ฒ์ ์ฌ์ฉํ๋ฉด catsService ๋ฉค๋ฒ๋ฅผ ํ ์ค์์ ์ ์ธ๊ณผ ์ด๊ธฐํ๋ฅผ ๋์์ ํ ์ ์์ด ์ฝ๋๋ฅผ ๊ฐ๊ฒฐํ๊ฒ ๋ง๋ค ์ ์์ต๋๋ค.
์์กด์ฑ ์ฃผ์
Nest๋ ์์กด์ฑ ์ฃผ์ (Dependency Injection, DI)์ด๋ผ๋ ๊ฐ๋ ฅํ ์ค๊ณ ํจํด์ ์ค์ฌ์ผ๋ก ๊ตฌ์ถ๋์ด ์์ต๋๋ค. ์ด ๊ฐ๋ ์ ๋ํด์๋ Angular ๊ณต์ ๋ฌธ์์ ํ๋ฅญํ ๊ธ์ ์ฐธ๊ณ ํด ๋ณด๋ ๊ฒ์ ์ ๊ทน ์ถ์ฒํฉ๋๋ค.
Nest์์๋ TypeScript์ ๊ธฐ๋ฅ ๋๋ถ์ ์์กด์ฑ ๊ด๋ฆฌ๊ฐ ๋งค์ฐ ๊ฐ๋จํฉ๋๋ค. ์์กด์ฑ์ ํ์ ๊ธฐ๋ฐ์ผ๋ก ์๋ ํด๊ฒฐ๋๊ธฐ ๋๋ฌธ์ ๋๋ค. ์๋ ์์ ์์๋, Nest๊ฐ catsService ํ์ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก CatsService์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๊ฑฐ๋ (์ฑ๊ธํค์ผ ๊ฒฝ์ฐ ์ด๋ฏธ ์์ฑ๋ ์ธ์คํด์ค๋ฅผ ์ฌ์ฌ์ฉ), ์ด๋ฅผ ์ปจํธ๋กค๋ฌ์ ์์ฑ์์ ์ฃผ์ ํด ์ค๋๋ค. ๋๋ ์ง์ ๋ ํ๋กํผํฐ์ ํ ๋นํด ์ค๋๋ค:
constructor(private catsService: CatsService) {}
์ค์ฝํ
ํ๋ก๋ฐ์ด๋๋ ์ผ๋ฐ์ ์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ ์๋ช ์ฃผ๊ธฐ์ ์ผ์นํ๋ ์๋ช (scope)์ ๊ฐ์ง๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ด ๋ถํธ์คํธ๋ฉ๋ ๋, ๋ชจ๋ ์์กด์ฑ์ด ํด๊ฒฐ๋์ด์ผ ํ๋ฉฐ, ์ด๋ ๊ณง ๋ชจ๋ ํ๋ก๋ฐ์ด๋๊ฐ ์ธ์คํด์คํ๋๋ค๋ ๋ป์ ๋๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ด ์ข ๋ฃ๋๋ฉด ๋ชจ๋ ํ๋ก๋ฐ์ด๋๋ ์๋ฉธ๋ฉ๋๋ค. ํ์ง๋ง, ํ๋ก๋ฐ์ด๋๋ฅผ ์์ฒญ ๋จ์ (request-scoped)๋ก ์ค์ ํ๋ ๊ฒ๋ ๊ฐ๋ฅํฉ๋๋ค. ์ด ๊ฒฝ์ฐ ํ๋ก๋ฐ์ด๋์ ์๋ช ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฒด๊ฐ ์๋ ํน์ ์์ฒญ์ ํ์ ๋ฉ๋๋ค. ์ด๋ฌํ ๊ธฐ๋ฒ์ ๋ํ ์์ธํ ๋ด์ฉ์ Injection Scopes ์ฅ์์ ํ์ธํ ์ ์์ต๋๋ค.
์ปค์คํ ํ๋ก๋ฐ์ด๋
Nest์๋ ์ ์ด์ ์ญ์ (Inversion of Control, IoC) ์ปจํ ์ด๋๊ฐ ๋ด์ฅ๋์ด ์์ด, ํ๋ก๋ฐ์ด๋ ๊ฐ์ ๊ด๊ณ๋ฅผ ๊ด๋ฆฌํฉ๋๋ค. ์ด ๊ธฐ๋ฅ์ ์์กด์ฑ ์ฃผ์ ์ ๊ธฐ๋ฐ์ด ๋๋ฉฐ, ์ง๊ธ๊น์ง ์ค๋ช ํ ๊ฒ๋ณด๋ค ํจ์ฌ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
Nest์์๋ ๋ค์ํ ๋ฐฉ์์ผ๋ก ํ๋ก๋ฐ์ด๋๋ฅผ ์ ์ํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ๋จ์ ๊ฐ (value), ํด๋์ค (class), ๋น๋๊ธฐ/๋๊ธฐ ํฉํ ๋ฆฌ (async/sync factory)๋ก ์ ์ํ ์ ์์ต๋๋ค. ํ๋ก๋ฐ์ด๋ ์ ์ ๋ฐฉ์์ ๋ํ ๋ ๋ง์ ์์ ๋ Dependency Injection ์ฅ์์ ํ์ธํ ์ ์์ต๋๋ค.
์ ํ์ ํ๋ก๋ฐ์ด๋
๋๋๋ก ๋ชจ๋ ์์กด์ฑ์ด ๋ฐ๋์ ํด๊ฒฐ๋์ด์ผ ํ๋ ๊ฒ์ ์๋๋๋ค. ์๋ฅผ ๋ค์ด, ํด๋์ค๊ฐ ์ค์ ๊ฐ์ฒด์ ์์กดํ์ง๋ง ํด๋น ์ค์ ์ด ์ ๊ณต๋์ง ์๋ ๊ฒฝ์ฐ ๊ธฐ๋ณธ๊ฐ์ ์ฌ์ฉํ๋๋ก ํ๊ณ ์ถ์ ์ ์์ต๋๋ค. ์ด๋ฌํ ๊ฒฝ์ฐ ํด๋น ์์กด์ฑ์ ์ ํ์ (optional)์ผ๋ก ๊ฐ์ฃผ๋๋ฉฐ, ์ค์ ํ๋ก๋ฐ์ด๋๊ฐ ์๋๋ผ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํด์๋ ์ ๋ฉ๋๋ค.
์ด๋ฌํ ์์กด์ฑ์ ์ ํ์ ์ผ๋ก ํ์ํ๋ ค๋ฉด ์์ฑ์ ์๊ทธ๋์ฒ์์ @Optional() ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฉ๋๋ค.
import { Injectable, Optional, Inject } from '@nestjs/common';
@Injectable()
export class HttpService<T> {
constructor(@Optional() @Inject('HTTP_OPTIONS') private httpClient: T) {}
}
์ ์์ ์์๋ ์ปค์คํ ํ๋ก๋ฐ์ด๋๋ฅผ ์ฌ์ฉํ๊ณ ์๊ธฐ ๋๋ฌธ์ HTTP_OPTIONS๋ผ๋ ์ปค์คํ ํ ํฐ์ ํฌํจ์ํจ ๊ฒ์ ๋๋ค. ์ด์ ์์ ๋ค์์๋ ์์ฑ์ ๊ธฐ๋ฐ ์ฃผ์ ๋ฐฉ์์ ๋ณด์ฌ์ฃผ์์ผ๋ฉฐ, ์ด ๋ฐฉ์์์๋ ์์กด์ฑ์ ์์ฑ์์ ํด๋์ค ํ์ ์ผ๋ก ๋ช ์ํ์ฌ ์ฃผ์ ๋ฐ์ต๋๋ค.
์ปค์คํ ํ๋ก๋ฐ์ด๋์ ํด๋น ํ ํฐ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง์ ๋ํ ์์ธํ ๋ด์ฉ์ Custom Providers ์ฅ์ ์ฐธ๊ณ ํ์ธ์.
์์ฑ ๊ธฐ๋ฐ ์ฃผ์
์ง๊ธ๊น์ง ์ฌ์ฉํ ๋ฐฉ์์ ์์ฑ์ ๊ธฐ๋ฐ ์ฃผ์ (Constructor-based Injection)์ด๋ผ๊ณ ํ๋ฉฐ, ํ๋ก๋ฐ์ด๋๋ฅผ ์์ฑ์ ๋ฉ์๋๋ฅผ ํตํด ์ฃผ์ ํ๋ ๋ฐฉ์์ ๋๋ค. ํ์ง๋ง ํน์ ์ํฉ์์๋ ์์ฑ ๊ธฐ๋ฐ ์ฃผ์ (Property-based Injection)์ด ์ ์ฉํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด, ์์ ํด๋์ค๊ฐ ํ๋ ์ด์์ ํ๋ก๋ฐ์ด๋์ ์์กดํ ๋, ํ์ ํด๋์ค์์ ์ด๋ฅผ super()๋ฅผ ํตํด ๋ชจ๋ ์ ๋ฌํ๋ ๊ฒ์ ๋ฒ๊ฑฐ๋ก์ธ ์ ์์ต๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ์๋ @Inject() ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์์ฑ ์์ค์์ ์ง์ ์ฌ์ฉํ์ฌ ์ด๋ฅผ ํผํ ์ ์์ต๋๋ค.
import { Injectable, Inject } from '@nestjs/common';
@Injectable()
export class HttpService<T> {
@Inject('HTTP_OPTIONS')
private readonly httpClient: T;
}
๊ฒฝ๊ณ
ํด๋์ค๊ฐ ๋ค๋ฅธ ํด๋์ค๋ฅผ ์์ํ์ง ์๋ ๊ฒฝ์ฐ์๋ ์ผ๋ฐ์ ์ผ๋ก ์์ฑ์ ๊ธฐ๋ฐ ์ฃผ์ ์ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ ์ข์ต๋๋ค. ์์ฑ์๋ฅผ ํตํด ์ด๋ค ์์กด์ฑ์ด ํ์ํ์ง ๋ช ํํ ๋๋ฌ๋๋ฏ๋ก, @Inject๋ก ์์ฑ์ ์ฃผ์ ํ๋ ๋ฐฉ์๋ณด๋ค ๊ฐ๋ ์ฑ ๋ฐ ์ฝ๋ ์ดํด๋ ์ธก๋ฉด์์ ์ฐ์ํฉ๋๋ค.
ํ๋ก๋ฐ์ด๋ ๋ฑ๋ก
CatsService๋ผ๋ ํ๋ก๋ฐ์ด๋์ ์ด๋ฅผ ์ฌ์ฉํ๋ CatsController๋ผ๋ ์๋น์๋ฅผ ์ ์ํ์ผ๋ฏ๋ก, ์ด์ Nest์ ์ด ์๋น์ค๋ฅผ ๋ฑ๋กํด์ผ ํฉ๋๋ค. ๊ทธ๋์ผ Nest๊ฐ ์์กด์ฑ์ ํด๊ฒฐํ๊ณ ์ฃผ์ ํ ์ ์์ต๋๋ค. ์ด๋ฅผ ์ํด app.module.ts ํ์ผ์ ์ด์ด @Module() ๋ฐ์ฝ๋ ์ดํฐ ์์ providers ๋ฐฐ์ด์ CatsService๋ฅผ ์ถ๊ฐํฉ๋๋ค.
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 {}
์ด์ Nest๋ CatsController ํด๋์ค์ ์์กด์ฑ์ ์ ์์ ์ผ๋ก ํด๊ฒฐํ ์ ์๊ฒ ๋ฉ๋๋ค.
ํ์ฌ๊น์ง์ ๋๋ ํฐ๋ฆฌ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์์ผ ํฉ๋๋ค:
src/
โโโ cats/
โ โโโ dto/
โ โ โโโ create-cat.dto.ts
โ โโโ interfaces/
โ โ โโโ cat.interface.ts
โ โโโ cats.controller.ts
โ โโโ cats.service.ts
โโโ app.module.ts
โโโ main.ts
์๋ ์ค์น
์ง๊ธ๊น์ง ์ฐ๋ฆฌ๋ Nest๊ฐ ์์กด์ฑ ํด๊ฒฐ์ ๋๋ถ๋ถ์ ์๋์ผ๋ก ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ ์ดํด๋ดค์ต๋๋ค. ๊ทธ๋ฌ๋ ๊ฒฝ์ฐ์ ๋ฐ๋ผ Nest์ ๋ด์ฅ ์์กด์ฑ ์ฃผ์ ์์คํ ์ ๋ฒ์ด๋, ์ง์ ํ๋ก๋ฐ์ด๋ ์ธ์คํด์ค๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ๋์ ์ผ๋ก ์ธ์คํด์ค๋ฅผ ์์ฑํด์ผ ํ ์๋ ์์ต๋๋ค. ์๋์ ๋ ๊ฐ์ง ์ฃผ์ ๊ธฐ๋ฒ์ ๊ฐ๋จํ ์๊ฐํฉ๋๋ค:
- ๊ธฐ์กด ์ธ์คํด์ค๋ฅผ ์กฐํํ๊ฑฐ๋ ํ๋ก๋ฐ์ด๋๋ฅผ ๋์ ์ผ๋ก ์ธ์คํด์คํํ๋ ค๋ฉด ๋ชจ๋ ์ฐธ์กฐ (Module reference)๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
- ์ ํ๋ฆฌ์ผ์ด์ ๋ถํธ์คํธ๋ฉ ์์ ์ ํ๋ก๋ฐ์ด๋ (์: ์ค์ ์๋น์ค ๋ฑ)๊ฐ ํ์ํ๋ค๋ฉด, bootstrap() ํจ์ ๋ด์์ ์ฃผ์ ๋ฐ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํ ์ ์์ต๋๋ค. ์ด๋ ๋ ๋ฆฝํ ์ ํ๋ฆฌ์ผ์ด์ ๊ตฌ์ฑ ์ ์ ์ฉํฉ๋๋ค. (์์ธํ ๋ด์ฉ์ Standalone applications ์ฅ ์ฐธ๊ณ )
๋ชจ๋ (Modules)
๋ชจ๋ (Module)์ @Module() ๋ฐ์ฝ๋ ์ดํฐ๊ฐ ๋ถ์ ํด๋์ค์ ๋๋ค. ์ด ๋ฐ์ฝ๋ ์ดํฐ๋ Nest๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์กฐ๋ฅผ ํจ์จ์ ์ผ๋ก ๊ตฌ์ฑํ๊ณ ๊ด๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉํ๋ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ์ ๊ณตํฉ๋๋ค.
๋ชจ๋ Nest ์ ํ๋ฆฌ์ผ์ด์ ์ ์ต์ ํ๋์ ๋ชจ๋, ์ฆ ๋ฃจํธ ๋ชจ๋์ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ์ด๋ Nest๊ฐ ์ ํ๋ฆฌ์ผ์ด์ ๊ทธ๋ํ๋ฅผ ๊ตฌ์ถํ๋ ์์์ ์ญํ ์ ํฉ๋๋ค. ์ด ๊ทธ๋ํ๋ ๋ชจ๋๊ณผ ํ๋ก๋ฐ์ด๋ ๊ฐ์ ๊ด๊ณ ๋ฐ ์์กด์ฑ์ Nest๊ฐ ๋ด๋ถ์ ์ผ๋ก ํด๊ฒฐํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์๊ท๋ชจ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฃจํธ ๋ชจ๋ ํ๋๋ง์ผ๋ก ์ถฉ๋ถํ ์ ์์ง๋ง, ์ผ๋ฐ์ ์ผ๋ก๋ ๊ทธ๋ ์ง ์์ต๋๋ค. Nest์์๋ ๋ชจ๋ ๋จ์์ ๊ตฌ์ฑ์ด ๊ถ์ฅ๋๋ฉฐ, ๋๋ถ๋ถ์ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ฌ๋ฌ ๋ชจ๋์ ๊ฐ์ง๊ณ ์๊ณ , ๊ฐ ๋ชจ๋์ ๋ฐ์ ํ๊ฒ ๊ด๋ จ๋ ๊ธฐ๋ฅ๋ค์ ์บก์ํํฉ๋๋ค.
@Module() ๋ฐ์ฝ๋ ์ดํฐ๋ ํ๋์ ๊ฐ์ฒด๋ฅผ ์ธ์๋ก ๋ฐ์ผ๋ฉฐ, ์ด ๊ฐ์ฒด๋ ๋ชจ๋์ ๊ตฌ์ฑํ๋ ๋ค์ํ ์์ฑ๋ค์ ์ ์ํฉ๋๋ค.
providers | ์ด ๋ชจ๋์์ Nest ์ธ์ ํฐ์ ์ํด ์ธ์คํด์คํ ๋ ํ๋ก๋ฐ์ด๋๋ค (๊ทธ๋ฆฌ๊ณ ์ต์ํ ์ด ๋ชจ๋ ๋ด์์ ๊ณต์ ๋ ์ ์๋ ๊ฒ๋ค) |
controllers | ์ด ๋ชจ๋์ ์ ์๋ ์ปจํธ๋กค๋ฌ ์งํฉ, Nest๊ฐ ์ด๋ค์ ์ธ์คํด์คํ ํด์ผ ํจ |
imports | ์ด ๋ชจ๋์์ ํ์ํ ํ๋ก๋ฐ์ด๋๋ฅผ ๋ด๋ณด๋ด๋ (import) ์ธ๋ถ ๋ชจ๋๋ค ๋ชฉ๋ก |
exports | ์ด ๋ชจ๋์์ ๋ค๋ฅธ ๋ชจ๋๋ค์ด ์ฌ์ฉํ ์ ์๋๋ก ๋ด๋ณด๋ผ (export) ํ๋ก๋ฐ์ด๋์ ์ผ๋ถ - ํ๋ก๋ฐ์ด๋ ์์ฒด ๋๋ ํด๋น ํ ํฐ (provide ๊ฐ) ๋ง์ ์ง์ ํ ์ ์์ |
๋ชจ๋์ ๊ธฐ๋ณธ์ ์ผ๋ก ํ๋ก๋ฐ์ด๋๋ฅผ ์บก์ํํฉ๋๋ค. ์ฆ, ํ์ฌ ๋ชจ๋์ ์ผ๋ถ์ด๊ฑฐ๋ ๋ค๋ฅธ ๋ชจ๋์์ ๋ช ์์ ์ผ๋ก export ๋ ํ๋ก๋ฐ์ด๋๋ง ์ฃผ์ ํ ์ ์์ต๋๋ค. ๋ชจ๋์์ export ๋ ํ๋ก๋ฐ์ด๋๋ ํด๋น ๋ชจ๋์ ๊ณต๊ฐ ์ธํฐํ์ด์ค (API) ์ญํ ์ ํ๋ฉฐ, ๋ค๋ฅธ ๋ชจ๋์ด ์ด ๋ชจ๋๊ณผ ์ํธ์์ฉํ ์ ์๋๋ก ํฉ๋๋ค.
๊ธฐ๋ฅ ๋ชจ๋ (Feature Modules)
์์ ์์ CatsController์ CatsService๋ ๋ฐ์ ํ ๊ด๊ณ๋ฅผ ๊ฐ์ง๋ฉฐ ๋์ผํ ๋๋ฉ์ธ์ ๋ด๋นํฉ๋๋ค. ๋ฐ๋ผ์ ์ด ๋์ ํ๋์ ๊ธฐ๋ฅ ๋ชจ๋ (feature module)๋ก ๋ฌถ๋ ๊ฒ์ด ํ๋นํฉ๋๋ค. ๊ธฐ๋ฅ ๋ชจ๋์ ํน์ ๊ธฐ๋ฅ๊ณผ ๊ด๋ จ๋ ์ฝ๋๋ฅผ ์กฐ์งํํ๋ฉฐ, ๋ช ํํ ๊ฒฝ๊ณ์ ๋ ๋์ ๊ตฌ์กฐ๋ฅผ ์ ์งํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค. ์ด๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ ํ ๊ท๋ชจ๊ฐ ์ปค์ง์๋ก ๋์ฑ ์ค์ํด์ง๋ฉฐ, SOLID ์์น๊ณผ๋ ์ ๋ถํฉํฉ๋๋ค.
์ด์ CatsModule์ ์์ฑํ์ฌ ์ปจํธ๋กค๋ฌ์ ์๋น์ค๋ฅผ ์ด๋ป๊ฒ ๋ฌถ๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
})
export class CatsModule {}
ํํธ
CLI๋ฅผ ์ฌ์ฉํ์ฌ ๋ชจ๋์ ์์ฑํ๋ ค๋ฉด, ๋ค์ ๋ช ๋ น์ด๋ฅผ ์คํํ๋ฉด ๋ฉ๋๋ค: nest g module cats
์์์๋ cats.module.ts ํ์ผ์์ CatsModule์ ์ ์ํ๊ณ , ์ด ๋ชจ๋๊ณผ ๊ด๋ จ๋ ๋ชจ๋ ํ์ผ์ cats ๋๋ ํฐ๋ฆฌ๋ก ์ด๋์์ผฐ์ต๋๋ค. ์ด์ ๋ง์ง๋ง์ผ๋ก ํด์ผ ํ ์ผ์, ์ด CatsModule์ ๋ฃจํธ ๋ชจ๋ (AppModule)์ import ํ๋ ๊ฒ์ ๋๋ค. AppModule์ app.module.ts ํ์ผ์ ์ ์๋์ด ์์ต๋๋ค.
import { Module } from '@nestjs/common';
import { CatsModule } from './cats/cats.module';
@Module({
imports: [CatsModule],
})
export class AppModule {}
ํ์ฌ ๋๋ ํฐ๋ฆฌ ๊ตฌ์กฐ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค:
src/
โโโ cats/
โ โโโ dto/
โ โ โโโ create-cat.dto.ts
โ โโโ interfaces/
โ โ โโโ cat.interface.ts
โ โโโ cats.controller.ts
โ โโโ cats.module.ts
โ โโโ cats.service.ts
โโโ app.module.ts
โโโ main.ts
๊ณต์ ๋ชจ๋
Nest์์๋ ๋ชจ๋์ด ๊ธฐ๋ณธ์ ์ผ๋ก ์ฑ๊ธํค (singleton)์ผ๋ก ๋์ํ๋ฏ๋ก, ์ฌ๋ฌ ๋ชจ๋ ๊ฐ์ ๋์ผํ ํ๋ก๋ฐ์ด๋ ์ธ์คํด์ค๋ฅผ ๋ณ๋ค๋ฅธ ์ค์ ์์ด ์ฝ๊ฒ ๊ณต์ ํ ์ ์์ต๋๋ค.
๋ชจ๋ ๋ชจ๋์ ์๋์ ์ผ๋ก ๊ณต์ ๋ชจ๋ (shared module)์ ๋๋ค. ํ ๋ฒ ์์ฑ๋ ๋ชจ๋ ๋ชจ๋์ ๋ค๋ฅธ ์ด๋ค ๋ชจ๋์์๋ ์ฌ์ฌ์ฉํ ์ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด, CatsService ์ธ์คํด์ค๋ฅผ ์ฌ๋ฌ ๋ค๋ฅธ ๋ชจ๋์์ ๊ณต์ ํ๊ณ ์ ํ๋ค๋ฉด, ๋จผ์ ํด๋น ํ๋ก๋ฐ์ด๋๋ฅผ exports ๋ฐฐ์ด์ ์ถ๊ฐํ์ฌ export ํด์ผ ํฉ๋๋ค. ์๋์ ๊ฐ์ด ์ค์ ํฉ๋๋ค:
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
exports: [CatsService]
})
export class CatsModule {}
์ด์ CatsModule์ import ํ๋ ์ด๋ ๋ชจ๋์์๋ CatsService์ ์ ๊ทผํ ์ ์์ผ๋ฉฐ, ์ด ์๋น์ค๋ ๋ค๋ฅธ ๋ชจ๋ ๋ชจ๋๊ณผ ๋์ผํ ์ธ์คํด์ค๋ฅผ ๊ณต์ ํ๊ฒ ๋ฉ๋๋ค.
๋ง์ฝ CatsService๋ฅผ ํ์ํ ๊ฐ ๋ชจ๋์ ์ง์ ๋ฑ๋กํ๋ค๋ฉด, ์๋น์ค๋ ์๋ํ๊ธด ํ์ง๋ง ๋ชจ๋๋ง๋ค ๋ณ๋์ ์ธ์คํด์ค๊ฐ ์์ฑ๋ฉ๋๋ค. ์ด๋ ๊ฒ ๋๋ฉด ๊ฐ์ ์๋น์ค๋ฅผ ์ฌ๋ฌ ๋ฒ ์์ฑํ๊ฒ ๋์ด ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๋์ด ์ฆ๊ฐํ ์ ์์ผ๋ฉฐ, ๋ด๋ถ ์ํ๋ฅผ ์ ์งํ๋ ์๋น์ค์ ๊ฒฝ์ฐ ์ํ ๋ถ์ผ์น์ ๊ฐ์ ์๊ธฐ์น ์์ ๋์์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
CatsService๋ฅผ CatsModule์ด๋ผ๋ ๋ชจ๋ ์์ ์บก์ํํ๊ณ exports๋ฅผ ํตํด ์ธ๋ถ๋ก ๋ด๋ณด๋์ผ๋ก์จ, ์ด ๋ชจ๋์ ๊ฐ์ ธ๋ค ์ฐ๋ ๋ชจ๋ ๊ณณ์์ ๋์ผํ ์ธ์คํด์ค๋ฅผ ์ฌ์ฌ์ฉํ๊ฒ ๋ฉ๋๋ค. ์ด ๋ฐฉ์์ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ์ ์ค์ด๊ณ , ๋ชจ๋ ๊ฐ ๋์์ ์์ธก ๊ฐ๋ฅํ๊ฒ ํ๋ฉฐ, ๊ณต์ ์ํ๋ ๋ฆฌ์์ค๋ฅผ ์ผ๊ด๋๊ฒ ๊ด๋ฆฌํ ์ ์๋๋ก ๋์์ค๋๋ค.
์ด๋ NestJS์ ๊ฐ์ ํ๋ ์์ํฌ์ ๋ชจ๋ํ์ ์์กด์ฑ ์ฃผ์ (DI)์ด ์ ๊ณตํ๋ ํต์ฌ ์ฅ์ ์ค ํ๋๋ก, ์๋น์ค๋ค์ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ฐ์ ๊ฑธ์ณ ํจ์จ์ ์ผ๋ก ๊ณต์ ํ ์ ์๊ฒ ํด ์ค๋๋ค.
๋ชจ๋ ์ฌ ๋ด๋ณด๋ด๊ธฐ (Module re-exporting)
์์ ๋ณธ ๊ฒ์ฒ๋ผ, ๋ชจ๋์ ๋ด๋ถ์ ํ๋ก๋ฐ์ด๋๋ฅผ export ํ ์ ์์ต๋๋ค. ๋๋ถ์ด, import ํ ๋ค๋ฅธ ๋ชจ๋์ ๋ค์ export ํ์ฌ ์ธ๋ถ๋ก ์ ๋ฌํ ์๋ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด ์๋์ ๊ฐ์ด CoreModule์ด CommonModule์ import ํ๊ณ ๋์์ export ํ๋ฉด, CoreModule์ import ํ๋ ๋ค๋ฅธ ๋ชจ๋๋ค์์๋ ๋ณ๋๋ก CommonModule์ import ํ์ง ์์๋ ํด๋น ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๊ฒ ๋ฉ๋๋ค.
@Module({
imports: [CommonModule],
exports: [CommonModule],
})
export class CoreModule {}
์์กด์ฑ ์ฃผ์
๋ชจ๋ ํด๋์ค์์๋ ํ๋ก๋ฐ์ด๋๋ฅผ ์ฃผ์ ๋ฐ์ ์ ์์ต๋๋ค (์: ์ค์ ๊ฐ์ ์ฌ์ฉํ๊ธฐ ์ํด).
import { Module } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Module({
controllers: [CatsController],
providers: [CatsService],
})
export class CatsModule {
constructor(private catsService: CatsService) {}
}
ํ์ง๋ง ๋ชจ๋ ํด๋์ค ์์ฒด๋ ์ํ ์์กด์ฑ (circular dependency) ๋๋ฌธ์ ํ๋ก๋ฐ์ด๋๋ก ์ฃผ์ ๋ ์๋ ์์ต๋๋ค.
์ ์ญ ๋ชจ๋
์ด๋์์๋ ๋์ผํ ๋ชจ๋ ์งํฉ์ ๋ฐ๋ณต์ ์ผ๋ก import ํด์ผ ํ๋ค๋ฉด, ์ด๋ ๋ฒ๊ฑฐ๋ก์ธ ์ ์์ต๋๋ค. Angular์๋ ๋ฌ๋ฆฌ, Nest์์๋ ํ๋ก๋ฐ์ด๋๊ฐ ์ ์ญ ๋ฒ์๊ฐ ์๋ ๋ชจ๋ ๋ฒ์์ ๋ฑ๋ก๋ฉ๋๋ค. ์ฆ, Nest์์๋ ์ด๋ค ๋ชจ๋์ ํ๋ก๋ฐ์ด๋๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด, ๋จผ์ ํด๋น ๋ชจ๋์ import ํด์ผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํฌํผ, ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ปค๋ฅ์ ๋ฑ๊ณผ ๊ฐ์ด ์ ํ๋ฆฌ์ผ์ด์ ์ ์ญ์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉ๋์ด์ผ ํ๋ ํ๋ก๋ฐ์ด๋ ์งํฉ์ ์ ๊ณตํ๊ณ ์ถ๋ค๋ฉด, ํด๋น ๋ชจ๋์ @Global() ๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ๋ถ์ฌ ์ ์ญ ๋ชจ๋ (Global Module)๋ก ๋ง๋ค์ด์ผ ํฉ๋๋ค.
import { Module, Global } from '@nestjs/common';
import { CatsController } from './cats.controller';
import { CatsService } from './cats.service';
@Global()
@Module({
controllers: [CatsController],
providers: [CatsService],
exports: [CatsService],
})
export class CatsModule {}
@Global() ๋ฐ์ฝ๋ ์ดํฐ๋ ํด๋น ๋ชจ๋์ ์ ์ญ ๋ฒ์ (Global scope)๋ก ๋ง๋ญ๋๋ค. ์ ์ญ ๋ชจ๋์ ์ผ๋ฐ์ ์ผ๋ก ๋ฃจํธ ๋ชจ๋์ด๋ ์ฝ์ด ๋ชจ๋์์ ๋จ ํ ๋ฒ๋ง ๋ฑ๋ก๋์ด์ผ ํฉ๋๋ค. ์ ์์์์์ฒ๋ผ CatsService๊ฐ ์ ์ญ ๋ชจ๋๋ก ์ ๊ณต๋๋ฉด, ์ด๋ฅผ ์ฌ์ฉํ๋ ค๋ ๋ค๋ฅธ ๋ชจ๋๋ค์ CatsModule์ imports ๋ฐฐ์ด์ ๋ช ์ํ ํ์ ์์ด ๋ฐ๋ก ์ฃผ์ ๋ฐ์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
ํํธ
๋ชจ๋ ๊ฒ์ ์ ์ญ์ผ๋ก ๋ง๋๋ ๊ฒ์ ๋ฐ๋์งํ ์ค๊ณ ๋ฐฉ์์ด ์๋๋๋ค. ์ ์ญ ๋ชจ๋์ ๋ณด์ผ๋ฌํ๋ ์ดํธ๋ฅผ ์ค์ด๋ ๋ฐ ๋์์ด ๋ ์๋ ์์ง๋ง, ์ผ๋ฐ์ ์ผ๋ก๋ imports ๋ฐฐ์ด์ ํตํด ๋ช ์์ ์ผ๋ก ๋ชจ๋์ API๋ฅผ ๊ณต์ ํ๋ ๋ฐฉ์์ด ๊ตฌ์กฐ์ ์ด๊ณ ์ ์ง๋ณด์์ ์ ๋ฆฌํฉ๋๋ค. ์ด ๋ฐฉ์์ ํ์ํ ๊ตฌ์ฑ์์์๋ง ๊ณต์ ํ๋๋ก ํ๋ฉฐ, ์ ํ๋ฆฌ์ผ์ด์ ๋ด์ ๋ถํ์ํ ๊ฒฐํฉ๋๋ฅผ ๋ฐฉ์งํ๋ ๋ฐ ๋์์ด ๋ฉ๋๋ค.
๋์ ๋ชจ๋
Nest์ ๋์ ๋ชจ๋ (Dynamic Module)์ ๋ฐํ์์ ๋ชจ๋์ ๊ตฌ์ฑํ ์ ์๋๋ก ํด์ค๋๋ค. ์ด๋ ํน์ ์ต์ ์ด๋ ์ค์ ์ ๋ฐ๋ผ ์ ์ฐํ๊ณ ์ฌ์ฉ์ ์ ์ ๊ฐ๋ฅํ ๋ชจ๋์ ์์ฑํด์ผ ํ ๋ ํนํ ์ ์ฉํฉ๋๋ค. ์๋๋ ๋์ ๋ชจ๋์ด ์๋ํ๋ ๋ฐฉ์์ ๋ํ ๊ฐ๋จํ ๊ฐ์์ ๋๋ค.
import { Module, DynamicModule } from '@nestjs/common';
import { createDatabaseProviders } from './database.providers';
import { Connection } from './connection.provider';
@Module({
providers: [Connection],
exports: [Connection],
})
export class DatabaseModule {
static forRoot(entities = [], options?): DynamicModule {
const providers = createDatabaseProviders(options, entities);
return {
module: DatabaseModule,
providers: providers,
exports: providers,
};
}
}
ํํธ
forRoot() ๋ฉ์๋๋ ๋์ ๋ชจ๋์ ๋๊ธฐ์ ์ผ๋ก ๋๋ ๋น๋๊ธฐ (Promise ๊ธฐ๋ฐ)๋ก ๋ฐํํ ์ ์์ต๋๋ค.
์ด ๋ชจ๋์ ๊ธฐ๋ณธ์ ์ผ๋ก @Module() ๋ฐ์ฝ๋ ์ดํฐ์ ๋ฉํ๋ฐ์ดํฐ์ ์ ์๋ Connection ํ๋ก๋ฐ์ด๋๋ฅผ ์ ๊ณตํฉ๋๋ค. ํ์ง๋ง forRoot() ๋ฉ์๋์ ์ ๋ฌ๋ entities์ options ๊ฐ์ฒด์ ๋ฐ๋ผ, ๋ฆฌํฌ์งํฐ๋ฆฌ์ ๊ฐ์ ์ถ๊ฐ์ ์ธ ํ๋ก๋ฐ์ด๋ ์งํฉ๋ ํจ๊ป ๋ ธ์ถํฉ๋๋ค. ๋์ ๋ชจ๋์ด ๋ฐํํ๋ ์์ฑ๋ค์ ๊ธฐ๋ณธ ๋ชจ๋์ ๋ฉํ๋ฐ์ดํฐ๋ฅผ ๋ฎ์ด์ฐ์ง ์๊ณ ํ์ฅํฉ๋๋ค. ์ด ๋ฐฉ์ ๋๋ถ์, ์ ์ ์ผ๋ก ์ ์ธ๋ Connection ํ๋ก๋ฐ์ด๋์ ๋์ ์ผ๋ก ์์ฑ๋ ๋ฆฌํฌ์งํฐ๋ฆฌ ํ๋ก๋ฐ์ด๋๋ค์ ๋ชจ๋ ํด๋น ๋ชจ๋์์ export ํ ์ ์์ต๋๋ค.
์ ์ญ ๋ฒ์์์ ๋์ ๋ชจ๋์ ๋ฑ๋กํ๊ณ ์ถ๋ค๋ฉด, ๋ฐํ ๊ฐ์ฒด์ global ์์ฑ์ true๋ก ์ค์ ํ์ธ์.
{
global: true,
module: DatabaseModule,
providers: providers,
exports: providers,
}
์ฃผ์
์์ ์ธ๊ธํ๋ฏ์ด, ๋ชจ๋ ๊ฒ์ ์ ์ญ์ผ๋ก ๋ง๋๋ ๊ฒ์ ๋ฐ๋์งํ ์ค๊ณ ๋ฐฉ์์ด ์๋๋๋ค.
DatabaseModule์ ๋ค์๊ณผ ๊ฐ์ ๋ฐฉ์์ผ๋ก import ๋ฐ ์ค์ ํ ์ ์์ต๋๋ค:
import { Module } from '@nestjs/common';
import { DatabaseModule } from './database/database.module';
import { User } from './users/entities/user.entity';
@Module({
imports: [DatabaseModule.forRoot([User])],
})
export class AppModule {}
๋์ ๋ชจ๋์ ๋ค์ re-export (์ฌ๋ด๋ณด๋ด๊ธฐ) ํ๋ ค๋ฉด, exports ๋ฐฐ์ด์์ forRoot() ๋ฉ์๋๋ฅผ ํธ์ถํ์ง ์๊ณ ๋ชจ๋ ์์ฒด๋ง ๋์ดํ๋ฉด ๋ฉ๋๋ค.
import { Module } from '@nestjs/common';
import { DatabaseModule } from './database/database.module';
import { User } from './users/entities/user.entity';
@Module({
imports: [DatabaseModule.forRoot([User])],
exports: [DatabaseModule],
})
export class AppModule {}
์ด ์ฃผ์ ๋ Dynamic Modules ์ฅ์์ ๋ ์์ธํ ๋ค๋ฃจ๊ณ ์์ผ๋ฉฐ, ์๋ํ๋ ์์ ๋ ํจ๊ป ํฌํจ๋์ด ์์ต๋๋ค.
ํํธ
์ด ์ฅ์์๋ ConfigurableModuleBuilder๋ฅผ ์ฌ์ฉํ์ฌ ๋์ ์์ค์ ์ฌ์ฉ์ ์ ์๊ฐ ๊ฐ๋ฅํ ๋์ ๋ชจ๋์ ๊ตฌ์ถํ๋ ๋ฐฉ๋ฒ๋ ๋ฐฐ์ธ ์ ์์ต๋๋ค.
Reference
'๐ ๊ณต์ ๋ฌธ์ ๋ฒ์ญ > Nest.js' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[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 |
[Nest.js] Overview - First Steps, Controllers (0) | 2025.07.05 |
[Nest.js] Introduction (0) | 2025.07.04 |