본문으로 바로가기

Controller, @Param, @Body, @Query ...

category Node, Nest, Deno/🦁 Nest.js 2020. 9. 24. 22:59

docs.nestjs.com/controllers

 

Documentation | NestJS - A progressive Node.js framework

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reac

docs.nestjs.com

 

Controllers are responsible for handling incoming requests and returning responses to the client.

 

즉, 컨트롤러는 프론트로부터 적절한 정보를 받아 로직을 처리하는 부분입니다. 

node express 썼을 때의 controller와 기능이 동일하다고 보시면 됩니다. 다만 비즈니스 로직을 Provider인 Srvice에 정의하고, Controller에서는 url과 연결시키는 역할만 합니다.

 

 


 

nest cli를 통해 컨트롤러 하나를 생성해봅시다.

nest g co movies

 

movies라는 이름의 컨트롤러를 생성한 결과는 다음과 같습니다.

 

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

@Controller('movies')
export class MoviesController {}

 

그리고 자동으로 app.modules.ts에 import되어 appModule 클래스의 데코레이터에 들어갔습니다.

사실, appModule에는 다른 모듈을 전부 합친 하나의 appModule만이 들어가야 합니다.

이 부분은 추후에 다루겠습니다.

 

import { Module } from '@nestjs/common';
import { MoviesController } from './movies/movies.controller';

@Module({
  imports: [],
  controllers: [MoviesController],
  providers: [],
})
export class AppModule {}

 

 

Controller

 

nest 커맨드를 통해 생성한 컨트롤러를 다음과 같이 수정합니다.

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

@Controller('movies')
export class MoviesController {
  @Get()
  getAll(): string {
    return 'this will return all movies';
  }

  @Get('/:id')
  getOne(): string {
    return 'this will return one movie';
  }
}

 

movies라는 이름의 컨트롤러를 만들어줬으므로 위 코드는

/movies

/movies/3

과 같은 url에 반응합니다.

 

 

 

url 파라미터 받아오기 @Param

 

express에서는 req.params로 얻어오던 방식이 nest에서는 다음과 같이 바뀌었습니다.

 

url의 파라미터를 얻기위해서는 함수의 파라미터로 해당 값을 받아야 합니다.

@Param("이름") "원하는 이름" 꼴로 가져옵니다.

import { Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common';

@Controller('movies')
export class MoviesController {
  @Get()
  getAll(): string {
    return 'this will return all movies';
  }

  @Get('/:id')
  getOne(@Param('id') movieId: string): string {
    return `this will return one movie, id: ${movieId}`;
  }
}

 

 

body 받아오기 @Body

 

req.body가 아니라 다음과 같이 @Body()를 통해 가져올 수 있습니다.

@Body() "할당하고 싶은 변수 명" 꼴입니다.

 

그리고 express와 달리 따로 res.json을 하지 않아도 return을 그대로 하면 json 꼴로 넘어가는 것을 보실 수 있습니다.

편함!

import { Body, Controller, Delete, Get, Param, Patch, Post } from '@nestjs/common';

@Controller('movies')
export class MoviesController {
  @Post()
  create(@Body() movieData) {
    console.log(movieData); // json
    return movieData;
  }

  @Patch('/:id')
  patch(@Param('id') movieId: string, @Body() updateData) {
    return {
      updatedMovie: movieId,
      ...updateData,
    };
  }
}

 

 

url 내 쿼리 가져오기 @Query

 

http://localhost:5000/movies/search?year=2020

와 같이 year라는 이름의 쿼리를 받아오고 싶습니다.

@Query("쿼리 이름") "원하는 이름"

@Controller('movies')
export class MoviesController {
  @Get('/search')
  search(@Query('year') searchingYear: number) {
    return `We are Searching made after: ${searchingYear}`;
  }

}

 

 

🚨 주의) 라우터의 순서

 

express에서도 그랬지만,

아래와 같은 순서로 라우터를 배치하면 search도 id의 일종로 받아들이기 때문에 순서를 바꿔주야 합니다.

router.get("/:id")
router.get("/search")

nest 또한 마찬가지이므로 순서에 신경써줍시다.

@Controller('movies')
export class MoviesController {

  // 이렇게 해야 search가 :id로 잡히지 않음
  
  @Get('/search')
  search() {
    return `We are Searching title: ${}`;
  }

  @Get('/:id')
  getOne(@Param('id') movieId: string): string {
    return `this will return one movie, id: ${movieId}`;
  }
}

 

 

@Req, @Res로 request, response 객체 살펴보기

 

express에서 타입을 가져올 수 있습니다.

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

@Controller('')
export class AppController {
  @Get()
  home(@Req() request: Request, @Res() response: Response) {
    console.log(Object.keys(request));
    console.log(Object.keys(response));
    return 'this is home';
  }
}

 

그런데 이런 방식으로 req, res를 직접 이용하는 것은 좋지 않습니다. req, res는 express에서 가져오는 객체입니다. 그러나 종종 빠른 속도를 위해 fastify를 사용할 수도 있습니다. express로 사용하다 fastify로 전환하면 @req, @res는 전환되지 않습니다. 따라서 @Req, @Res는 차후 퍼포먼스 문제로 위해 전환할 경우를 대비하기 위해 사용하지 않는 것이 좋습니다.

 

 

앞서 언급한 내용 외에도 아래와 같은 것들을 이용할 수 있습니다.

 

응답에 header를 @headers를 이용해 붙일 수도 있고, @Ip로 특정 아이피를 받아올 수도 있으며 @request,를 통해 요청의 상세한 내용을 확인할 수도 있습니다. @HttpCode(204)와 같이 특정한 statusCode를 삽입할 수도 있습니다.  자세한 내용은 공식문서!

 

@Request() req
@Response(), @Res()* res
@Next() next
@Session() req.session
@Param(key?: string) req.params / req.params[key]
@Body(key?: string) req.body / req.body[key]
@Query(key?: string) req.query / req.query[key]
@Headers(name?: string) req.headers / req.headers[name]
@Ip() req.ip
@HttpCode(status:number)  

 

 

* For compatibility with typings across underlying HTTP platforms (e.g., Express and Fastify), Nest provides @Res() and @Response() decorators. @Res() is simply an alias for @Response(). Both directly expose the underlying native platform response object interface. When using them, you should also import the typings for the underlying library (e.g., @types/express) to take full advantage.

 

Note that when you inject either @Res() or @Response() in a method handler, you put Nest into Library-specific mode for that handler, and you become responsible for managing the response. When doing so, you must issue some kind of response by making a call on the response object (e.g., res.json(...) or res.send(...)), or the HTTP server will hang.

 


darren, dev blog
블로그 이미지 DarrenKwonDev 님의 블로그
VISITOR 오늘 / 전체