NestJS - Controller

Y·2024년 10월 19일

NestJS의 컨트롤러: 요청 처리 및 라우팅 개념

NestJS에서 컨트롤러(Controller)는 클라이언트로부터 들어오는 요청을 처리하고 응답을 반환하는 핵심 요소입니다. 컨트롤러는 주어진 요청에 따라 특정 동작을 수행하며, 라우팅 매커니즘을 통해 어떤 컨트롤러가 어떤 요청을 처리할지 제어합니다. 이번 포스팅에서는 컨트롤러의 역할, 라우팅 개념, 그리고 컨트롤러를 설정하는 방법에 대해 자세히 알아보겠습니다.


컨트롤러란 무엇인가?

NestJS에서 컨트롤러는 주로 HTTP 요청을 처리하는 역할을 합니다. 각 컨트롤러는 특정 요청을 처리하며, 하나의 컨트롤러는 여러 개의 라우트를 가질 수 있습니다. 라우트별로 다른 동작을 수행할 수 있도록 설계됩니다. 컨트롤러를 정의할 때는 클래스데코레이터를 사용하며, 데코레이터는 클래스에 메타데이터를 첨부하여 Nest가 요청을 특정 컨트롤러로 라우팅할 수 있도록 합니다.

컨트롤러 생성 예시

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

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

위 예시에서 @Controller('cats') 데코레이터는 cats라는 경로를 처리하는 컨트롤러를 정의합니다. @Get() 데코레이터는 HTTP GET 요청을 처리하는 라우트를 설정하며, findAll() 메서드는 요청을 처리하고 클라이언트에 응답을 반환합니다.


라우팅 및 경로 설정

컨트롤러는 기본적으로 HTTP 요청을 처리하기 위한 라우팅 경로를 정의합니다. @Controller() 데코레이터에 경로를 지정하여 관련된 라우트를 그룹화할 수 있으며, 이를 통해 코드의 중복을 줄일 수 있습니다. 예를 들어, cats 경로에 대한 모든 요청을 하나의 컨트롤러에서 처리하도록 설정할 수 있습니다.

라우트 경로와 HTTP 메서드

컨트롤러에서 경로를 설정할 때는 @Get(), @Post(), @Put(), @Delete() 등의 HTTP 메서드 데코레이터를 사용하여 특정 HTTP 메서드에 대한 요청을 처리합니다.

  • @Get() : GET 요청을 처리
  • @Post() : POST 요청을 처리
  • @Put() : PUT 요청을 처리
  • @Delete() : DELETE 요청을 처리

요청 객체(Request) 다루기

NestJS는 요청 객체에 접근할 수 있는 여러 데코레이터를 제공합니다. 가장 일반적으로 사용되는 것은 @Req() 데코레이터로, 이를 통해 Express의 요청 객체에 접근할 수 있습니다.

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';
  }
}

요청 객체에 대한 데코레이터 목록

NestJS는 요청 객체의 세부 속성에 접근할 수 있도록 여러 데코레이터를 제공합니다.

  • @Param(key?: string) : 경로 파라미터(req.params)
  • @Body(key?: string) : 요청 본문(req.body)
  • @Query(key?: string) : 쿼리 스트링(req.query)
  • @Headers(name?: string) : HTTP 헤더(req.headers)
  • @Ip() : 요청 IP(req.ip)

동적 경로 파라미터

때로는 정적 경로 대신 동적 경로 파라미터가 필요할 수 있습니다. 예를 들어, 특정 ID에 해당하는 리소스를 가져오기 위해 GET /cats/1와 같은 경로가 필요할 때, 동적 경로를 사용합니다. 이를 위해 @Param() 데코레이터를 사용하여 경로 파라미터에 접근할 수 있습니다.

동적 경로 파라미터 예시

@Get(':id')
findOne(@Param('id') id: string): string {
  return `This action returns a #${id} cat`;
}

위 코드에서 @Param('id')를 사용하여 경로 파라미터 id 값을 받아 처리할 수 있습니다.


비동기 요청 처리

NestJS는 비동기 요청 처리도 자연스럽게 지원합니다. 비동기 작업을 처리하기 위해 asyncawait을 사용할 수 있으며, Nest는 비동기 함수가 반환하는 Promise를 자동으로 처리합니다.

@Get()
async findAll(): Promise<any[]> {
  return [];
}

또한, Nest는 RxJS Observable 스트림을 반환하는 것을 지원하며, 자동으로 스트림을 구독하고 마지막에 방출된 값을 클라이언트에 전달합니다.


요청 본문 처리

POST 요청에서는 클라이언트로부터 데이터를 전달받아야 합니다. 이를 위해 @Body() 데코레이터를 사용하여 요청 본문을 처리합니다. TypeScript를 사용할 경우, DTO(Data Transfer Object)를 정의하여 데이터의 형식을 명시할 수 있습니다.

DTO 정의 및 사용 예시

export class CreateCatDto {
  name: string;
  age: number;
  breed: string;
}

@Post()
async create(@Body() createCatDto: CreateCatDto) {
  return 'This action adds a new cat';
}

DTO를 사용하면 데이터 구조를 명확하게 정의할 수 있고, Nest의 파이프(Pipe) 기능을 활용하여 유효성 검사를 수행할 수 있습니다.


상태 코드와 헤더 설정

NestJS는 기본적으로 GET 요청에 대해 200 상태 코드를 반환하고, POST 요청에는 201 상태 코드를 반환합니다. 이를 변경하려면 @HttpCode() 데코레이터를 사용할 수 있습니다. 또한, @Header() 데코레이터를 통해 응답 헤더를 설정할 수 있습니다.

@Post()
@HttpCode(204)
create() {
  return 'This action adds a new cat';
}

@Post()
@Header('Cache-Control', 'none')
create() {
  return 'This action adds a new cat';
}

컨트롤러 등록

컨트롤러를 생성한 후에는 모듈에 등록해야 합니다. 컨트롤러는 항상 모듈에 속하며, 이를 통해 Nest는 컨트롤러를 인식하고 요청을 처리합니다.

import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';

@Module({
  controllers: [CatsController],
})
export class AppModule {}

결론

NestJS의 컨트롤러는 HTTP 요청을 처리하고 응답을 반환하는 중요한 역할을 합니다. 컨트롤러는 요청 라우팅, 비동기 처리, 데이터 유효성 검사 등 다양한 기능을 쉽게 구현할 수 있으며, Nest의 의존성 주입과 데코레이터 시스템을 통해 복잡한 로직을 깔끔하게 관리할 수 있습니다.

컨트롤러의 구조와 Nest가 제공하는 다양한 기능을 적절히 활용하면, 확장 가능하고 유지보수에 용이한 서버 애플리케이션을 만들 수 있습니다.

profile
연세대학교 산업공학과 웹개발 JavaScript

0개의 댓글