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)
위와같은 요청결과가 나오게 된다.
@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}`;
}
위처럼 적용시키면
nest에서 데이터 처리를 어떠한 방식으로 하는지 알 수 있다.
이제 컨트롤러를 통해서 백엔드에서 요청을 처리하고 응답을 가공하는 방식을 알아보았다!
'BackEnd > NodeJs' 카테고리의 다른 글
[NestJs] 2- 데코레이터 (0) | 2022.11.15 |
---|---|
[NestJs] 01 - NestJS 설치 (0) | 2022.11.15 |
[Node.js] 서버에서 클라이언트로 파일 전송하기 (2) | 2022.10.06 |
[node.js] multer,fetch를 활용한 파일 업로드 (0) | 2022.10.06 |