NestJS - A progressive Node.js framework
nest 홈페이지 docs를 따라서 사용해보는 것 입니다.
Nest cli 를 사용하여 설치합니다.
$ npm i -g @nestjs/cli
$ nest new nest-example
cli에서 생성한 핵심 파일들 입니다.
src
app.controller.ts // 단일 경로가있는 기본 컨트롤러 샘플.
app.module.ts // 애플리케이션의 루트 모듈입니다.
main.ts // 핵심 기능 NestFactory을 사용하여 Nest 애플리케이션 인스턴스를 생성하는 애플리케이션의 엔트리 파일입니다 .
express를 기반으로 사용하는 플랫폼 platform-express를 사용하게 위해 NestExpressApplication('@nestjs/platform-express') 추가해줍니다.
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { NestExpressApplication } from '@nestjs/platform-express'
async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule);
await app.listen(3000);
}
bootstrap();
컨트롤러는 들어오는 요청 을 처리 하고 클라이언트에 응답 을 반환 합니다.
$ nest g controller cats
명령어를 실해하면 아래와 같은 컨트롤러가 자동으로 생성됩니다.
import { Controller } from '@nestjs/common';
@Controller('member')
export class MemberController {}
Providers는 Nest의 기본 개념입니다.
컨트롤러에서 http요청을 처리하고 더 복한한 처리는 Providers에 위임합니다.
@Injectable() 데이레이터가 있는 클레스입니다.
//cats.service.ts
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;
}
}
의존성 주입
constructor(private catsService: CatsService) {}
module 설정
@Module({
controllers: [CatsController],
providers: [CatsService],
})
모듈은 @Module()
데코레이터로 주석이 달린 클래스 입니다. @Module()
장식은 메타 데이터를 제공 둥지 차종의 애플리케이션 구조를 구성하도록 사용.
디렉토리 구조
동적모듈
Nest 모듈 시스템에는 동적 모듈 이라는 강력한 기능이 포함되어 있습니다. 이 기능을 사용하면 공급자를 동적으로 등록하고 구성 할 수있는 사용자 지정 가능한 모듈을 쉽게 만들 수 있습니다.
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 {}
미들웨어는 라우트 핸들러 이전 에 호출되는 함수입니다 . 미들웨어 기능은 요청 및 응답 객체에 액세스 할 수 next()있으며 애플리케이션의 req, res 에서 미들웨어 기능에 액세스 할 수 있습니다
/* eslint-disable @typescript-eslint/ban-types */
import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response } from 'express';
@Injectable()
export class LoggerMiddleware implements NestMiddleware {
use(req: Request, res: Response, next: Function) {
console.log('Request...');
next();
}
}
@Module()
데코레이터 에는 미들웨어를 위한 장소가 없습니다 . 대신 configure()
를 사용하여 설정합니다.
NestModule
인터페이스를 받고 LoggerMiddleware
에서 설정합니다.
import { Module,NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CatsModule } from './cats/cats.module';
import { LoggerMiddleware } from './common/middieware/logger.middleware';
@Module({
imports: [CatsModule],
controllers: [AppController],
providers: [AppService],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(LoggerMiddleware)
.forRoutes('cats');
}
}
apply() 단일 미들웨어를 사용하거나 여러 개의 미들웨어 를 지정하기 위해 여러 인수를 사용할 수 있습니다 .
apply(cors(), helmet(), logger)
패턴 기반 경로도 지원됩니다. 예를 들어 별표는 와일드 카드 로 사용되며 모든 문자 조합과 일치합니다.
forRoutes({ path: 'ab*cd', method: RequestMethod.ALL });
exclude()방법으로 특정 경로를 쉽게 제외 할 수 있습니다.
.exclude(
{ path: 'cats', method: RequestMethod.GET },
{ path: 'cats', method: RequestMethod.POST },
'cats/(.*)',
)
미들웨어를 등록 된 모든 경로에 한 번에 바인딩 use()
하려면 INestApplication
인스턴스에서 제공 하는 메서드를 사용할 수 있습니다 .
const app = await NestFactory.create(AppModule);
app.use(logger);
await app.listen(3000);
애플리케이션 전체에서 처리되지 않은 모든 예외를 처리 하는 내장 예외 레이어 가 있습니다.
기본 처리에서 대부분 처리 할수있지만 예외처리에 대한 모든 권한 을 원할 수 있습니다 . 예를 들어 로깅을 추가하거나 일부 동적 요인을 기반으로 다른 JSON 스키마를 사용할 수 있습니다.
이를 통해 정확한 제어 흐름과 클라이언트로 다시 전송되는 응답 내용을 제어 할 수 있습니다.
@Catch(HttpException)
형식으로 HttpException
를 처리할 수 있고 쉼표로 구분하여 여러 유형을 설정할 수도 있다. 아무것도 없이 @Catch()
경우 모든 예외 처리에 해당합니다.
import { ExceptionFilter, Catch, ArgumentsHost, HttpException } from '@nestjs/common';
import { Request, Response } from 'express';
@Catch(HttpException)
export class HttpExceptionFilter implements ExceptionFilter {
catch(exception: HttpException, host: ArgumentsHost) {
const ctx = host.switchToHttp();
const response = ctx.getResponse<Response>();
const request = ctx.getRequest<Request>();
const status = exception.getStatus();
response
.status(status)
.json({
statusCode: status,
timestamp: new Date().toISOString(),
path: request.url,
});
}
}
파이프에는 두 가지 일반적인 사용 사례가 있습니다.
두 경우 모두 파이프는 컨트롤러 라우트 핸들러에arguments
의해 처리됩니다. . Nest는 메소드가 호출되기 직전에 파이프를 삽입하고 메소드로 향하는 인수를 수신하고 이에 대해 작동합니다.그 후 경로 처리기가 (잠재적으로) 변환 된 인수와 함께 호출됩니다.
Pipe가 예외를 throw하면 예외 계층 (전역 예외 필터 및 현재 컨텍스트에 적용되는 모든 예외 필터 )에서 처리됩니다. Pipe에서 예외가 발생하면 컨트롤러가 실행되지 않습니다.
Nest는 기본적으로 사용할 수있는 6 개의 파이프와 함께 제공됩니다.
ValidationPipe
ParseIntPipe
ParseBoolPipe
ParseArrayPipe
ParseUUIDPipe
DefaultValuePipe
ParseIntPipe
에서는 파이프를 특정 경로 처리기 메서드와 연결하고 메서드가 호출되기 전에 실행되는지 확인하려고합니다. 매개변수에서 수행합니다.
@Get(':id')
async findOne(@Param('id', ParseIntPipe) id: number) {
return this.catsService.findOne(id);
}
위의 경우에 id가 숫자가 아닐경우 예외처리 됩니다.
사용자 지정 파이프
ValidationPipe. 처음에는 단순히 입력 값을 취하고 즉시 동일한 값을 반환하여 식별 함수처럼 작동합니다.
import { PipeTransform, Injectable, ArgumentMetadata } from '@nestjs/common';
@Injectable()
export class ValidationPipe implements PipeTransform {
transform(value: any, metadata: ArgumentMetadata) {
return value;
}
}
PipeTransform<T, R> 파이프로 구현 해야하는 일반 인터페이스입니다.
모든 파이프는 인터페이스 계약 transform()
을 이행하는 방법을 구현해야합니다 PipeTransform
. 이 메소드에는 두 개의 매개 변수가 있습니다.
value
metadata
export interface ArgumentMetadata {
type: 'body' | 'query' | 'param' | 'custom';
metatype?: Type<unknown>;
data?: string;
}
이건 nest에서 지원하는 ArgumentMetadata 인터페이스 입니다.
type body @Body(), query @Query(), param @Param()또는 맞춤 매개 변수 인지 여부를 확인
metatype 인수의 메타 유형을 제공합니다 (예 : String. 참고 : 값은 undefined경로 핸들러 메소드 서명에서 유형 선언을 생략하거나 바닐라 JavaScript를 사용하는 경우입니다.
data 데코레이터에 전달 된 문자열 (예 :) @Body('string'). 그건 undefined당신이 장식은 빈 괄호 떠날 경우.
여기까지 간단하게 nestjs 의 공식 홈페이지를 따라왔습니다.
실습 해본 내용
https://github.com/KH-Lim/nest-example