[NestJS] 03 - 컨트롤러
BackEnd/NodeJs

[NestJS] 03 - 컨트롤러

728x90

Nest의 컨트롤러는 MVC 패턴에서의 컨트롤러이다.

 

즉, 들어오는 요청(request)를 받고 그 처리결과를 응답(response)로 돌려주는 인터페이스 역할을 한다.

 

컨트롤러는 라우팅 메커니즘을 통해 컨트롤러가 받는 요청을 분류한다.

 

이전 글에서 서버를 구동시키고 동작하는법은 익혔다. 그렇다면 소스코드를 한번 살펴보자

 

 

// app.controller.ts

import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(): string {
    return this.appService.getHello();
  }
}

 

@Controller 데코레이터를 클래스에 선언하는 것으로 해당클래스를 컨트롤러의 역할을 하도록 만든다.

 

 

getHello 함수는 @Get 데코레이터를 가지고 있다. 인자로 아무것도 없는것은 루트경로 '/' 가 생략된것으로 생각할 수 있다.

 

 

 

@Get('/hello')
getHello2(): string {
  return this.appService.getHello();
}

위와같이 경로를 hello로 바꾸고 페이지(localhost:3000)에 접속하면 404 에러를 만날 수 있을 것이다.

 

 

localhost:3000/hello 주소로 변경해야 정상동작이 된다.

 

또한, @Controller 데코레이터에도 인자를 전달할 수 있는데, 이는 라우팅 경로의 prefix를 지정하는 것이다.

 

@Controller('app') 로 바꾼다면, 이제 http://localhost:3000/app/hello로 접속해야 한다.

 

 

 

 

와일드 카드

 

라우팅 패스는 와일드 카드를 사용할 수 있다.

 

@Get('he*lo')
getHello(): string {
  return this.appService.getHello();
}

즉 위처럼 작성한다면 helo,hello,he_lo 등의 경로들을 요청으로 받을 수 있다.

 

* 말고 ?,+,() 등도 정규표현식에서의 와일드카드와 똑같이 동작한다.

 

 

 

요청 객체

 

클라이언트는 요청을 보낼때 정보를 함께 전달하는 경우가 있다. Nest는 이런 데이터를 핸들러가 다룰 수 있는 객체로 변환하고, 이 객체는 @Req() 데코레이터를 이용하여 다룰 수 있다.

 

예제코드를 한번 보자

 

 

import { Request } from 'express';
import { Controller, Get, Req } from '@nestjs/common';
import { AppService } from './app.service';

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Get()
  getHello(@Req() req: Request): string {
    console.log(req);
    return this.appService.getHello();
  }
}

 

 

응답

 

 

nest g resource Users

명령어를 사용하면 Users리소스에 대한 CRUD API가 생성된다.

 

 

경로http method응답 상태 코드body

/users POST 201 This action adds a new user
/users GET 200 This action returns all users
/users/1 GET 200 This action returns a #1 user
/users/1 PATCH 200 This action updates a #1 user
/users/1 DELETE 200 This action removes a #1 user

(출처 : https://wikidocs.net/148200)

 

위와같은 요청결과가 나오게 된다.

 

postman을 통한 테스트

 

 

@Get()
findAll(@Res() res) {
  const users = this.usersService.findAll()

  return res.status(200).send(users);
}

예를들어 위처럼 적었다면, userService의 findAll 즉,

 

@Injectable()
export class UsersService {
  create(createUserDto: CreateUserDto) {
    return 'This action adds a new user';
  }

  findAll() {
    return `This action returns all users`;
  }

  findOne(id: number) {
    return `This action returns a #${id} user`;
  }

  update(id: number, updateUserDto: UpdateUserDto) {
    return `This action updates a #${id} user`;
  }

  remove(id: number) {
    return `This action removes a #${id} user`;
  }
}

해당부분의 문자열 부분을 찾아 반환하여 응답으로 제출하게 되는 것이다.

 

이 부분은 해당 예제 코드를 VSCODE에 띄어놓고 몇번 왔다갔다 하면서 보면 쉽게 이해할 수 있다.

 

 

 

 

헤더

 

Nest는 응답헤더또한 자동으로 구성해 준다.

 

 

응답에 커스텀 헤더를 추가하고싶다면 @Header 데코레이터를 추가하면 된다. 인자로는 헤더 이름과 값을 받는다.

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

@Header('Custom', 'Test Header')
@Get(':id')
findOneWithHeader(@Param('id') id: string) {
  return this.usersService.findOne(+id);
}

 

 

 

리디렉션

 

서버가 요청을 처리한 후에 클라이언트를 다른 페이지로 이동시키는 방법이다.

 

이 경우 @Redirect 데코레이터를 사용하면 쉽게 구현이 가능하다.

 

두번째 인자로는 상태코드를 넣는다.

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

@Redirect('https://nestjs.com', 301)
@Get(':id')
findOne(@Param('id') id: string) {
  return this.usersService.findOne(+id);
}

 

 

하위 도메인

 

 

만약 현재 도메인이 example.com이고, api요청을 받는 도메인을 api.example.com으로 받는다면,

 

 

$ nest g co ApiController

위와같이 컨트롤러를 하나 생성한 후,

 

@Module({
  controllers: [ApiController, AppController],
    ...
})
export class AppModule { }

module에 연동해준다. 이때, 이미 app.controller.ts에 루트라우팅 경로를 가진 엔드포인트가 존재하므로, ApiController가 먼저 동작될 수 있도록 순서를 수정해준다.

 

@Controller({ host: 'api.example.com' }) // 하위 도메인 요청 처리 설정
export class ApiController {
  @Get() // 같은 루트 경로
  index(): string {
    return 'Hello, API'; // 다른 응답
  }
}

그 이후, 위와같이 Controller 인자에 하위 도메인을 기술하면 사용할 수 있다.

 

아래와 같이 각각의 요청에 잘 동작하는것을 알 수 있다.

$ curl http://localhost:3000
Hello World!
$ curl http://api.localhost:3000
Hello, API

 

 

 

페이로드

 

POST,PUT,PATCH 와같은 요청은 보통 데이터를 함께 실어 보낸다 (페이로드) 이러한 데이터 덩어리를 body라고 한다.

 

Nest에서는 이 body를 DTO(Data Transfer Object)를 정의하여 다룬다.

 

 

User리소스를 만들기 위해 POST/users로 들어오는 본문 CreateUserDto로 받고있다.

 

export class CreateUserDto {
  name: string;
  email: string;
}

 

 

@Post()
create(@Body() createUserDto: CreateUserDto) {
  const { name, email } = createUserDto;

  return `유저를 생성했습니다. 이름: ${name}, 이메일: ${email}`;
}

 

위처럼 적용시키면

 

postman 테스트

nest에서 데이터 처리를 어떠한 방식으로 하는지 알 수 있다.

 

 

이제 컨트롤러를 통해서 백엔드에서 요청을 처리하고 응답을 가공하는 방식을 알아보았다!

728x90