부트캠프를 다니면서 GraphQL 형식의 API를 작성하기 위해 컨트롤러가 아닌 리졸버(resolver)를 작성했다. 이번에 진행하는 프로젝트는 REST API를 사용하게 되어 컨트롤러를 작성하고 있다.
컨트롤러 개념이 부족한 것 같아 우선 NestJS 공식문서를 통해 기본적인 Controller 개념을 공부하려고 한다.
컨트롤러는 요청을 처리하고 클라이언트에게 응답을 돌려주는 역할을 한다.
컨트롤러의 목적은 애플리케이션에 대한 특정 요청을 수신하는 것이다. 라우팅 메커니즘은 어떤 컨트롤러가 어떤 요청을 수신할지를 제어한다. 일반적으로 각각의 컨트롤러에는 1개 이상의 라우트가 존재하고, 각각의 라우트는 서로 다른 기능을 수행한다.
기본적인 컨트롤러를 생성하려면 클래스와 데코레이터를 사용한다. 데코레이터는 클래스를 필수 메타데이터와 연결하고 Nest가 라우팅 맵을 생성하게 해준다. 라우팅 맵이란 요청을 요청에 해당하는 컨트롤러에 연결하는 것을 말한다.
아래 예제에서 @Controller()
데코레이터를 사용하는데, 이 데코레이터는 기본적인 컨트롤러를 정의하기 위해 필수적이다. cats
라는 선택적 라우트 경로 prefix를 지정하였다. @Controller
데코레이터에서 경로 prefix를 사용하면 연관된 라우트 세트를 쉽게 그룹화할 수 있고, 중복 코드를 최소화할 수 있다.
예를 들어, 라우트 /cats
에서 고양이 엔티티와의 상호작용을 관리하는 라우트 세트를 그룹화할 수 있다. 이 경우, @Controller
데코레이터에서 경로 prefix cats
를 지정함으로써 각각의 라우트에 대해 경로를 반복하지 않아도 된다.
// cats.controller.ts
import { Controller, Get } from '@nestjs/common';
@Controller('cats')
export class CatsController {
@Get()
findAll(): string {
return 'This action returns all cats';
}
}
findAll()
메서드 위에 있는 @Get()
HTTP 요청 메서드 데코레이터는 Nest에게 HTTP 요청에 대한 특정 엔드포인트를 핸들링하는 핸들러를 생성하라고 알려준다. 엔드포인트는 HTTP 요청 메서드와 라우트 경로에 연결된다.
핸들러의 라우트 경로는 컨트롤러에 선언한 prefix와 메서드의 데코레이터에 지정한 경로가 결합된 것을 말한다. 모든 라우트에 대해 prefix를 cats
로 선언했고, @Get()
데코레이터에서는 어떤 경로 정보도 추가하지 않았기 때문에, Nest는 GET /cats
요청을 이 핸들러(findAll)로 맵핑시킨다.
이전에 언급했듯이, 경로는 선택적 컨트롤러 경로 prefix와 요청 메서드 데코레이터에 선언한 경로 문자열을 포함한다. 예를 들어, 데코레이터 @Get('breed')
와 cats
경로 prefix가 결합되면 GET /cats/breed
와 같은 요청에 대한 라우트 맵핑이 생성된다.
위 예제에서 이 엔드포인트(/cats
)에 대해 GET 요청이 들어오면 Nest는 findAll()
메서드로 요청을 라우팅한다. 반드시 경로와 엮을 메서드를 선언해야 한다.
findAll()
메서드는 200 상태 코드와 응답(이 경우에는 단순한 문자열)을 반환한다. Nest가 응답을 조작하기 위한 두 가지 옵션을 사용한다는 개념이 존재한다.
내장 메서드를 사용하면 요청 핸들러가 자바스크립트 객체 또는 배열을 반환할 때, 자동으로 객체 또는 배열이 JSON으로 직렬화된다. 하지만 string
, number
, boolean
과 같은 자바스크립트 원시 타입을 반환하는 경우, Nest는 직렬화하지 않고 그대로 반환한다. 이 점이 응답 핸들링을 더 쉽게 해준다: 값을 반환하기만 하면 Nest가 나머지는 알아서 해준다.
Express
와 같은 라이브러리 특정 응답 객체를 사용할 수도 있다. findAll(@Res() response)
과 같이 메서드 핸들러에서 @Res()
데코레이터를 사용해 응답 객체가 주입(injected)될 수 있다.
이 접근 방식을 사용하면 해당 객체에 의해 노출되는 응답 핸들링 메서드를 사용할 수 있게 된다. 예를 들어, Express를 사용하면 response.status(200).send()
와 같은 코드를 사용해 응답을 구성할 수 있다.