Nest js 초기 설정부터 Controller 만지기

NestJS는 SOILD 아키텍쳐를 추구하고, bolierplate 코드를 지양하는 철학을 가진 JS 진형의 서버용 통합 Framework이다. 이러한 구조를 바탕으로 우리가 무엇을 해야할 지에 대해서 좀 더 집중하고 구조를 깔끔하게 관리할 수 있는게 바로 NestJS의 핵심 가치이다. 소프트웨어가 고도화됨에 따라 분명 많은 개발자가 자신만의 코드 작성 구조를 들고 올 것이고, 이러한 구조속에서 다같이 통일 가능한 구조를 찾아야 했기 때문에 NestJS가 이러한 통일의 역활을 하기 시작한것 같다.

설치

NestJS를 사용해보자. NestJS를 설치하는 방법은 2개다. 포스터에서는 패키지 툴을 이용해 자동으로 다운 받고 설치하고자 한다. 설치후 초기 프로젝트 생성까지 해보자

yarn globla add @nestjs/cli # yarn global add @nestjs/cli
nest new project-name

구조

구조에 대해서 명확하게 이해할 필요는 없다. 다만 잠깐 짚고 넘어가자면, 모든 파일이 싱글폰으로 구성되어 있으며 또한 modules에서 관리하고 데코레이터 패턴을 통해 보일러플레이트를 제공하는 구조인데 다 써보면서 천천히 이해해도 된다.

app.controller.spec.ts: controller의 unit test 파일

app.controller.ts: request, response를 맞아서 서비스와 연결해 주는 메서드들

app.modules.ts: 어플리케이션의 root module을 담는 파일

app.service.ts: 실제 기능 담당으로 메소드를 최소 단위로 분리해서 작성해야한다.

main.ts: main.ts에서는 어떤 express, fastify 둘중 어떤걸 사용할 수 있는지 선택할 수 있다. 진입점

src/
  app.controller.spec.ts
  app.controller.ts
  app.module.ts
  app.service.ts
  main.ts

NestFactory class: 에서는 여러 메소드를 담고 있으며 application obejct를 반환한다. 이는 지금 당장 이해할 필요없다.


기본 HTTP 플랫폼 설정

express나 fastify둘다 설정 가능하다. 따라서 express를 사용하자(Fastify써도 되는데 스타트업 기준으로써 이게 필요하다)

Express : 조금 느리다. 하지만 더 친절하고 좋은 커뮤니티 보유, @nestjs/platform-express

Fastify: 더 빠르다. 사용하기 어려운 커뮤니티 보유 - 진짜 2022년 기준으로 이걸로하면 모든걸 스스로 해쳐나가야 한다.

설치

express를 설치하고 main.ts에 명시해주면 된다.

yarn add @nestjs/platform-express

./src/main

import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);
  await app.listen(3000);
}
bootstrap();

Controllers

Controller: 클라이언트와 request, response를 직접적으로 처리하고 디테일한 처리는 service로 넘긴다. 컨트롤러는 요청에 대항 응답의 확실한 반환을 목표로 한다.

목적: 어플리케이션에 대한 특정 요청을 수신하고 반환 하는 것, Nestjs 에서는 데코레이터 패턴을 활용한다.

Hint: 만약에 빠르게 CRUD controller를 내장 validation으로 빠르게 만들고 싶다면 다음의 CLI를 참조하세요  CRUD generatornest g resource [name].


사용 데코레이터

아래의 데코레이터를 설치가 된 파일을 보면 볼 수 있다.

@Controller: class에 선언

@Get,Post,... : 라우팅 함수에 선언, HTTP 표준 메서드에 대해서 이를 method위에 작성하고 사용 @nestjs/common에 있다


응답

  • Status code: 성공적으로 메소드가 진행되면 status code 200이 Post(201) 자동으로 전달 된다. 이는 Nest 자체 Standard이며, 이에 대해서 옵션을 수정할 수 있다.
  • 만약에 특별히 응답 객체를 만들어서 전달하고자 한다면 Express의 경우 @Res를 사용해서 응답객체를 구성하여 전달 할 수 있다. 이 경우 Nest에서 자동으로 생성되는 Res의 헤더는 동작이 비활성화 된다.

주의: 자동응답과 수동응답은 잘 혼용되지 않습니다. 둘을 혼용하려면 @Res({ passthrough: true }) 처럼 데코레이터 안에 넣어서 작성해야 합니다.


Req객체에 접근

Req갹채애 접근하기 위해서는 @Req를 이용해 접근해 주면 됩니다.

Request객체는 @types/express 를 npm에서 설치하면 됩니다.

ex. cats.controller.ts

import { Controller, Get, Req } from '@nestjs/common';
import { Request } from 'express';

@Controller('cats')
export class CatsController {
  @Get()
  findAll(@Req() request: Request): string {
    return 'This action returns all cats';
  }
}

그외에도 여러 객체에 접근하기 위해서는 데코레이터 패턴을 사용해야 한다.

여러 패턴들

Decorator List

  • Resources: Nest는 8개의 표준 HTTP 메소드에 대해서 데코레이터를 제공한다. 헤더의 자동완성 기능 제공
@Post()
  create(): string {
    return 'This action adds a new cat';
  }
@Get()
  findAll(): string {
    return 'This action returns all cats';
  }
  • Route wildcard: Regex기반 라우트도 일부 지원된다. ? + ()은 지원되고 - . 은 그대로 해석된다. `@Get('abcd')`
  • Status Code: @HttpCode(204) @Post 같은 메소트아래 사용

@nestjs/common에서 HttpCode를 가져와야 함

  • Headers: @Header('Cache-Control', 'none') 호출해서 지정가능 @nestjs/common에서 Header
  • Redirection: @Redirect('https://nestjs.com', 301)
  • Route parameters:
@Get(':id')
findOne(@Param() params): string {
  console.log(params.id);
  return `This action returns a #${params.id} cat`;
}

@Get(':id')
findOne(@Param('id') id: string): string {
  return `This action returns a #${id} cat`;
}
  • Sub-Domain Routing: @Controller({ host: 'admin.example.com' })
  • Scopes: Nest에서는 들어오는 모든 요청에 대해 프로그램의 가동 전체에서 전부 공유를 한다. 이는Nest 자체가 싱글톤 인스턴스를 사용해 처리를 했기 때문이다. 이리고 이러한 처리는 별도의 스레드에서의 요청 응답을 막고 다중스레드에 따라 비동기와 상태 비저장 문제를 일으키지 않습니다. 따라서 이러한 방식은 정말 완전하고 안전한 구조를 만들게 도와줍니다. 다만 때로는 요청 기반의 수명이 바람직할 수 있습니다. 예를 들면 환자에게 언제나 새로운 데이터를 주는경우가 있습니다. 이때는 GraphQL 애플리케이션의 요청별 캐싱, 요청 추적 또는 멀티테넌시가 있습니다. 여기에서 범위를 제어하는 방법을 알아보세요.
  • Asynchronicity: async findAll(): Promise<any[]> , findAll(): Observable<any[] 이 두 코드를 쓰면 Nest 라우트 핸들러는 관찰 가능한 RxJs 스트림을 반환합니다. 그리고 이 스트림이 완료가 되면 Nest는 자동으로 스트림에서 마지막으로 내보낸 값을 반환해 준다.
  • Request payloads: (TypeScript를 사용하는 경우) DTO(데이터 전송 개체) 스키마를 결정해야 한다

마치며

이렇게 간략하게 정리해 보았다. 어려운 부분이 많을 것으로 예상되는데 NestJS의 경우 공식문제가 잘 나와있어 구태여 내가 다 일일히 정리할 필요보다는 간단한 정리 위주로 하면 좋을듯 하여 요약 정리로 만들었다.

좋은 웹페이지 즐겨찾기