nest g controller {이름}
을 사용하면, 바로 활용가능한 형태의 컨트롤러가 생성된다. 추가적으로 모듈에 등록도 된다. NestJs 공식문서에 예제를 보면서 구체적으로 살펴보자.
// cats.controller.ts
import { Controller, Get } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
return 'MEOW';
}
}
이 예제 코드는 GET /cats 요청을 받으면 또한 상태 코드 200과 함께 문자열 MEOW를 응답한다. @Get() 데코레이터에도 인수로 경로 지정이 가능한데, 예를 들어 @Controller('cats')의 @Get('profile')은 GET /cats/profile요청에 대응합니다.
client의 request 접근이 필요할땐 @Req() 데코레이터를 사용하면 된다. 이 객체는 default로 express의 request 객체를 따른다.
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';
}
}
res.status(200).send()
의 형식을 활용하였다.)POST 메서드같은 경우, HTTP 요청의 바디에서 데이터를 받아오는 것이 일반적이다. 이러한 데이터는 Nest의 핸들러 메서드에서 @Body() 데코레이터가 적용된 DTO 타입의 매개변수로 접근할 수 있다!!! DTO(데이터 전달 객체, Data Transfer Object)는 데이터가 네트워크를 통해 어떻게 전달되는지 정의하는 일종의 스키마 객체이며, 클래스로 정의할 수 있습니다.
// create-cats.dto.ts
export class CreateCatDto {
name: string;
age: number;
breed: string;
}
그리고 이렇게 정의한 DTO는 컨트롤러의 핸들러 메서드에서 다음과 같이 사용할 수 있다.
// cats.controller.ts
@Post()
async create(@Body() createCatDto: CreateCatDto) {
return 'This action adds a new cat';
}
모던 JavaScript에서 데이터를 다루는 일은 비동기적인 경우가 많습니다. 이에 대응하기 위해 Nest는 async 함수를 잘 지원합니다. async 함수는 지연된 결과값인 Promise 객체를 반환합니다. 그러므로 메서드에서 다음과 같이 Promise를 리턴하여도 잘 처리됩니다.
@Get()
async findAll(): Promise<any[]> {
...
return [];
}
컨트롤러를 완성하는 것만으로는 Nest에서 컨트롤러 클래스를 인식하지 못한다.(하지만 위에서 서술한 것처럼 nest g controller {이름}
를 통해서 컨트롤러를 만들었다면 자동으로 모듈에 컨트롤러가 등록된다) 컨트롤러는 모듈에 존속되어야하며, 그러려면 모듈 클래스의 @Module() 데코레이터에 controllers 옵션 배열로 컨트롤러를 지정해야합니다.
// app.module.ts
import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';
@Module({
controllers: [CatsController],
})
export class AppModule {}
참고: 네스트 공식문서
async함수인데 await을 이용하여 리턴하지 않아도 네스트가 알아서 잘해주는게 신기하네요!