NestJS의 package.json에는 엄청 많은 확장 모듈이 기본적으로 깔려 있다. dependencies 살펴 보면 그 기능은 다음과 같다.
"dependencies": {
"@nestjs/common": "^8.0.0",
"@nestjs/core": "^8.0.0",
"@nestjs/platform-express": "^8.0.0",
"reflect-metadata": "^0.1.13",
"rimraf": "^3.0.2",
"rxjs": "^7.2.0"
}
@nestjs/common
@nestjs/core
@nestjs/platform-express
: NestJS 안에서 자체적으로 동작하는 라이브러리.reflect-metadata
: 데코레이터 사용과 관련된 패키지.rimraf
: 지정한 파일이나 폴더를 지우는 rm --rf 명령어를 윈도우에서 사용할 수 있게 해주는 패키지.rxjs
: 비동기 및 이벤트 기반 프로그래밍을 작성하기 위한 라이브러리.controller(app.controller.ts)는 들어온 요청을 처리하고 클라이언트에 응답을 반환한다. 클라이언트에서 HTTP request를 보내면 controller가 이를 받아서 응답을 하는 구조다.
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): string {
return this.appService.getHello();
}
}
controller를 들어가 보면 AppController 클래스 안에서 appService를 사용하기 위해 의존성 주입을 한 걸 볼 수 있다. 그래서 해당 클래스에서 appService를 사용할 수 있고, appService 내부 메서드의 return 값이 controller에 내부에서 실행되어 반환된다.
물론 controller에서도 바로 return을 할 수 있지만 Nest는 그것을 지양한다. NestJS는 controller를 비지니스 로직과 구분 짓고 싶어 한다. 즉, controller는 그저 url을 매핑하고, 리퀘스트를 받고, 쿼리나 Body 등의 것들을 넘기는 역할만을 할 뿐이다. 비지니스 로직, 일반적인 실제의 기능 함수는 service단으로 간다.
조금 복잡하지만 유지보수와 가독성에 더 유리하다..고 한다. 😇
또한 controller의 데코레이터에서 라우팅을 할 수 있다. (아래처럼)
@Controller('customers')
export class AppController {
constructor(private readonly appService: AppService) {}
@Get('profile')
getHello(): string {
return this.appService.getHello();
}
}
라우팅 경로는 @Get
데코레이터의 인자가 된다. 이렇게 라우팅을 설정하면 localhost:포트넘버/customers
로 경로 접두사(prefix)를 지정할 수 있다. customers
경로 접두사와 데코레이터 @Get('profile')
을 결합하면 GET /customers/profile
로 경로가 매핑된다. 데코레이터에서 경로 접두사를 사용하면 반복적인 코드를 최소화할 수 있고 쉬운 그룹화가 가능하다.
import { Controller, Get, Req } from '@nestjs/common';
@Get('profile')
getHello(@Req() req: Request): string {
console.log(req);
return this.appService.getHello();
}
NestJS에서는 req, res 같은 요청 객체를 데코레이터 패턴으로 사용할 수 있다. 전용 데코레이터를 함수 인자에 넣어 주면 되는데, 반드시 import 한 후 사용해야 한다. (아니면 빨간 줄 뜬다) 타입스크립트를 사용할 경우 Request 타입도 지정해 주면 좋다. 이렇게 사용할 수 있는 전용 데코레이터들은 다음과 같다.
ㅤㅤㅤ제공하는 전용 데코레이터ㅤㅤㅤ | ㅤ 이들이 나타내는 일반적 개체 목록ㅤ |
---|---|
@Request(), @Req() | 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 |
@HostParam() | req.hosts |
'lee'라는 고객의 프로필을 가지고 오기 위해 @Get('profile/lee')
와 같이 요청해야 한다고 가정해 보자.
여기서 /lee
에 해당되는 부분은 동적으로 구성된다. 즉, 경로 구성에 사용되는 라우트 파라미터가 된다. 전달받은 파라미터는 함수 인자에 @Param 데코레이터로 주입(의존성 주입)받을 수 있다. 복수의 라우트 파라미터를 받는 상황이라면 아래 코드처럼 파라미터를 따로따로 받는다. 이때, @Param 데코레이터 괄호 안의 &&는 ~~~
@Get('profile/:name/:cusNum')
getHello(
@Param('name') name: string,
@Param('cusNum') cusNum: number,
): string {
console.log(req);
}