NEST 도입
Nest(NestJS)는 효율적이고 확장 가능한 Node.js 서버 측 애플리케이션을 구축하기 위한 프레임워크입니다. 이 프레임워크는 프로그레시브 자바스크립트를 사용하며, 타입스크립트로 구축되어 완벽하게 지원하지만 개발자는 순수 자바스크립트로 코딩할 수 있고, OOP(객체 지향 프로그래밍), FP(함수형 프로그래밍), FRP(기능적 반응형 프로그래밍)의 요소를 결합한 프레임워크입니다.
내부적으로 Nest는 Express(기본값)와 같은 강력한 HTTP 서버 프레임워크를 사용하며, 선택적으로 Fastify도 사용하도록 구성할 수 있습니다!
Nest는 이러한 일반적인 Node.js 프레임워크(Express/Fastify)보다 높은 수준의 추상화를 제공할 뿐만 아니라 해당 API를 개발자에게 직접 노출합니다. 따라서 개발자는 기본 플랫폼에서 사용할 수 있는 수많은 타사 모듈을 자유롭게 사용할 수 있습니다.
초기 설정된 프로젝트 설치하는 방법
$ git clone https://github.com/nestjs/typescript-starter.git project
$ cd project
$ npm install // yarn install
$ npm run start // yarn start
npm(또는 yarn)을 사용하여 코어 및 지원 파일을 설치하여 처음부터 새 프로젝트를 수동으로 만들 수도 있습니다. 물론 이 경우 프로젝트 상용구 파일을 직접 만들어야 합니다.
$ npm i --save @nestjs/core @nestjs/common rxjs reflect-metadata
프로젝트 생성하는 방법
설정
새 프로젝트를 설정하는 것은 Nest CLI를 사용하면 매우 간단합니다. npm이 설치되어 있으면 OS 터미널에서 다음 명령을 사용하여 새 Nest 프로젝트를 만들 수 있습니다:
$ npm i -g @nestjs/cli // yarn add @nestjs/cli
$ nest new project-name
프로젝트 이름 디렉토리가 생성되고, 노드 모듈과 몇 가지 다른 상용구 파일이 설치되며, src/ 디렉토리가 생성되어 몇 가지 핵심 파일로 채워집니다.
app.controller.ts | A basic controller with a single route. |
app.controller.spec.ts | The unit tests for the controller. |
app.module.ts | The root module of the application. |
app.service.ts | A basic service with a single method. |
main.ts | The entry file of the application which uses the core function NestFactory to create a Nest application instance. |
NestJS 컨트롤러(Controller) 개념 정리
NestJS에서 컨트롤러는 들어오는 요청을 처리하고 클라이언트에게 응답을 반환하는 역할을 합니다. 애플리케이션에서 특정 요청을 받기 위한 목적으로 사용되며, 라우팅 메커니즘을 통해 어떤 컨트롤러가 어떤 요청을 받을지 결정됩니다. 일반적으로 각 컨트롤러는 여러 라우트를 가지고 있으며, 다양한 라우트가 다른 요청을 처리할 수 있습니다.
컨트롤러의 주요 기능
- 라우팅: NestJS에서 라우팅은 컨트롤러를 통해 구현됩니다. 특정 경로에 대한 요청을 받고, 그에 대한 로직을 실행하여 응답을 반환합니다.
- 요청 객체 처리: 요청 객체를 통해 클라이언트로부터 받은 데이터에 접근할 수 있습니다. 이를 통해 필요한 작업을 수행할 수 있습니다.
- 응답 반환: 처리된 결과를 클라이언트에게 반환합니다. 상태 코드, 헤더, 본문 등을 포함한 응답을 컨트롤할 수 있습니다.
- 에러 처리: 요청 처리 중 발생할 수 있는 에러를 적절히 처리하고, 에러 응답을 반환합니다.
컨트롤러 구현 방법
- 컨트롤러 클래스 정의: @Controller() 데코레이터를 사용하여 클래스를 컨트롤러로 정의합니다. 데코레이터에는 이 컨트롤러의 라우트 경로를 지정할 수 있습니다.
- 라우트 핸들러 메소드 정의: 각 라우트에 대한 핸들러 메소드를 정의합니다. @Get(), @Post(), @Put(), @Delete() 등의 HTTP 메소드 데코레이터를 사용하여 메소드를 라우트와 연결합니다.
- 요청 데이터 처리: @Body(), @Param(), @Query() 등의 데코레이터를 사용하여 요청 본문, URL 파라미터, 쿼리 파라미터 등을 메소드 파라미터로 받아 처리할 수 있습니다.
- 응답 반환: 메소드에서 처리 결과를 반환하면, NestJS가 이를 클라이언트에게 응답으로 전송합니다. 필요에 따라 @Res() 데코레이터를 사용하여 응답 객체를 직접 제어할 수도 있습니다.
NestJS 프로바이저(Providers) 개념 정리
NestJS에서 프로바이저는 애플리케이션의 기본적인 구성 요소 중 하나로, 서비스, 리포지토리, 팩토리, 헬퍼 등 다양한 클래스가 프로바이더로 취급될 수 있습니다. 프로바이저의 핵심 아이디어는 의존성으로 주입될 수 있다는 것입니다. 이를 통해 객체 간 다양한 관계를 생성하고, 이러한 객체를 "연결"하는 기능을 대부분 Nest 런타임 시스템에 위임할 수 있습니다.
프로바이저의 주요 기능
- 의존성 주입(Dependency Injection): 프로바이저는 다른 클래스의 인스턴스를 생성하고 관리하는 데 필요한 의존성을 제공합니다. 이를 통해 코드의 재사용성과 테스트 용이성이 향상됩니다.
- 서비스 제공: 비즈니스 로직을 수행하는 서비스를 포함하여 다양한 기능을 애플리케이션에 제공합니다.
- 모듈 간 데이터 공유: 프로바이더를 통해 애플리케이션의 다른 부분 간에 데이터를 공유하고 접근할 수 있습니다.
프로바이저 구현 방법
- 프로바이더 등록: 모듈의 providers 배열에 프로바이저를 추가하여 등록합니다. 이를 통해 Nest가 의존성을 관리할 수 있게 됩니다.
- 의존성 주입 사용: 클래스의 생성자를 통해 필요한 의존성을 주입받습니다. Nest는 등록된 프로바이저 중에서 요청된 의존성을 찾아 자동으로 주입합니다.
- 커스텀 프로바이더: 표준 프로바이저 외에도, useValue, useClass, useFactory, useExisting 등 다양한 방법으로 커스텀 프로바이저를 생성할 수 있습니다. 이를 통해 더 유연한 의존성 관리가 가능해집니다.
프로바이저 종류
맞춤 공급자(Custom Providers)
- 개념: 맞춤 공급자는 NestJS의 의존성 주입 시스템을 사용하여, 표준 서비스나 값 이외의 복잡한 값을 제공할 때 사용됩니다. 이를 통해 애플리케이션의 유연성을 높일 수 있습니다.
- 용도: 맞춤 공급자는 표준적인 클래스나 값 이외에 복잡한 구성이나 동적 값, 조건부 서비스 제공 등에 사용됩니다. 다양한 방식(useValue, useClass, useFactory, useExisting)을 통해 유연하게 서비스를 제공할 수 있습니다. 예를 들어, 다른 데이터 소스를 동적으로 선택하거나, 특정 조건에 따라 서비스 구현을 변경할 때 유용합니다.
import { Module, Injectable, Inject } from '@nestjs/common';
@Injectable()
class ConfigService {
// ConfigService의 구현 내용
}
@Module({
providers: [
{
provide: 'CONFIG_OPTIONS',
useValue: { /* 설정 값 */ },
},
{
provide: ConfigService,
useFactory: (options) => new ConfigService(options),
inject: ['CONFIG_OPTIONS'],
},
],
})
export class AppModule {}
선택자 공급자(Selector Providers)
- 개념: 선택자 공급자에 대한 구체적인 정보는 제공되지 않았습니다. 일반적으로, 선택자는 특정 조건에 따라 서비스를 선택적으로 제공할 수 있는 메커니즘을 의미할 수 있습니다. NestJS 공식 문서에서는 이와 직접적으로 관련된 내용을 찾을 수 없었습니다.
- 용도: 선택자 공급자에 대한 구체적인 정보는 NestJS 공식 문서에서 직접적으로 언급되지 않았습니다. 일반적으로, 선택자는 특정 조건에 따라 서비스를 선택적으로 제공할 수 있는 메커니즘을 의미할 수 있으나, NestJS에서는 이를 '맞춤 공급자'의 일부로 볼 수 있습니다. 특히, 팩토리 제공자(useFactory)를 사용하여 요청에 따라 다른 서비스를 동적으로 선택하는 경우가 이에 해당할 수 있습니다.
import { Module, DynamicModule } from '@nestjs/common';
import { createDatabaseProviders } from './database.providers';
import { Connection } from './connection.interface';
@Module({})
export class DatabaseModule {
static forRoot(entities = [], options?): DynamicModule {
const providers = createDatabaseProviders(options, entities);
return {
module: DatabaseModule,
providers: providers,
exports: providers,
};
}
}
속성 기반 주입(Property-based Injection)
- 개념: 속성 기반 주입은 생성자 주입 대신 클래스의 속성에 직접 의존성을 주입하는 방식입니다. 이 방식은 특정 상황에서 의존성 주입을 더 유연하게 할 수 있게 해줍니다.
- 용도: 속성 기반 주입은 특정 상황에서 생성자 주입을 대체할 수 있는 방법으로, 클래스의 속성에 직접 의존성을 주입합니다. 이 방식은 특히, 클래스가 다른 클래스를 확장하고 있고, 부모 클래스에 의존성을 주입해야 할 때 유용할 수 있습니다. 또한, 선택적 의존성 주입이 필요한 경우에도 적합합니다.
import { Injectable, Inject } from '@nestjs/common';
@Injectable()
export class HttpService<T> {
@Inject('HTTP_OPTIONS')
private readonly httpOptions: T;
// HttpService의 구현 내용
}
공급자 등록(Provider Registration)
- 개념: 공급자 등록은 NestJS 모듈에 공급자를 등록하는 과정을 의미합니다. 이를 통해 해당 모듈 내에서 또는 전역적으로 공급자를 사용할 수 있게 됩니다.
- 용도: 공급자 등록은 모듈에 서비스나 값 공급자를 등록하여, 해당 모듈 내부 또는 애플리케이션 전역에서 사용할 수 있게 하는 과정입니다. 이를 통해 모듈 간의 의존성을 관리하고, 서비스의 재사용성과 테스트 용이성을 높일 수 있습니다. 모든 공급자 유형은 등록 과정을 거쳐 NestJS 의존성 주입 시스템에 포함됩니다.
import { Module } from '@nestjs/common';
import { CatsService } from './cats.service';
@Module({
providers: [CatsService],
})
export class CatsModule {}