Nest 시작하기 (1)

Ricky·2020년 10월 25일
2
post-thumbnail

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();

Controllers

컨트롤러는 들어오는 요청 을 처리 하고 클라이언트에 응답 을 반환 합니다.

$ nest g controller cats

명령어를 실해하면 아래와 같은 컨트롤러가 자동으로 생성됩니다.

import { Controller } from '@nestjs/common';

@Controller('member')
export class MemberController {}

Providers

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()데코레이터로 주석이 달린 클래스 입니다. @Module()장식은 메타 데이터를 제공 둥지 차종의 애플리케이션 구조를 구성하도록 사용.

  • providers
    모듈에서 사용할 공급자 provider ( service )
  • controllers
    모듈에서 사용할 컨트롤러 ( controller )
  • imports
    모듈 가져오기
  • exports
    모듈 내보내기

디렉토리 구조

Nest%20%E1%84%89%E1%85%B5%E1%84%8C%E1%85%A1%E1%86%A8%E1%84%92%E1%85%A1%E1%84%80%E1%85%B5%20(1)%20d42f0c243e2e44a6a27419fda1c872bd/Untitled.png

동적모듈

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);

Exception filters

애플리케이션 전체에서 처리되지 않은 모든 예외를 처리 하는 내장 예외 레이어 가 있습니다.

기본 처리에서 대부분 처리 할수있지만 예외처리에 대한 모든 권한 을 원할 수 있습니다 . 예를 들어 로깅을 추가하거나 일부 동적 요인을 기반으로 다른 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,
      });
  }
}

Pipes

파이프에는 두 가지 일반적인 사용 사례가 있습니다.

  • 변환 : 입력 데이터를 원하는 형식으로 변환 (예 : 문자열에서 정수로)
  • 유효성 검사 : 입력 데이터를 평가하고 유효하면 변경하지 않고 전달합니다. 그렇지 않으면 데이터가 올바르지 않을 때 예외를 발생시킵니다.

두 경우 모두 파이프는 컨트롤러 라우트 핸들러에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

profile
Developer

0개의 댓글