> For the complete documentation index, see [llms.txt](https://jakekwak.gitbook.io/nestjs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jakekwak.gitbook.io/nestjs/overview/untitled-1.md).

# Controlers

## Controllers

컨트롤러는 들어오는 **requests**을 처리하고 **responses**을 클라이언트에게 반환합니다..

![](https://docs.nestjs.com/assets/Controllers_1.png)

컨트롤러의 목적은 응용 프로그램에 대한 특정 요청을받는 것입니다. **routing** 메커니즘은 어떤 컨트롤러가 어떤 요청을 받는지 제어합니다. 종종 각 컨트롤러에는 하나 이상의 경로가 있으며 다른 경로는 다른 작업을 수행할 수 있습니다.

기본 컨트롤러를 만들기 위해 클래스와 **Decorators**를 사용합니다. 데코레이터는 클래스를 필요한 메타 데이터와 연결하고 Nest가 라우팅 맵을 생성 할 수 있도록합니다 (요청을 해당 컨트롤러에 연결).

## Routing

다음 예에서는 기본 컨트롤러를 정의하기 위해 **필수** 인`@Controller()` 데코레이터를 사용합니다. 선택적 경로 경로 접두사 `cats`를 지정합니다. `@Controller()`데코레이터에서 경로 접두사를 사용하면 관련된 경로 세트를 쉽게 그룹화하고 반복 코드를 최소화 할 수 있습니다. 예를 들어 `/customers`경로에서 고객 엔티티와의 상호 작용을 관리하는 경로 세트를 그룹화하도록 선택할 수 있습니다. 이 경우`@Controller()`데코레이터에서 경로 접두어 `customers`를 지정할 수 있으므로 파일의 각 경로에 대해 경로의 해당 부분을 반복 할 필요가 없습니다.

```typescript
@@filename(cats.controller)
import { Controller, Get } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  @Get()
  findAll(): string {
    return 'This action returns all cats';
  }
}
@@switch
import { Controller, Get } from '@nestjs/common';

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

> info **힌트** CLI를 사용하여 컨트롤러를 만들려면 간단히`$ nest g controller cats` 명령을 실행하십시오.

`findAll()`메소드 앞에있는 `@Get()` HTTP 요청 메소드 데코레이터는 Nest에게 HTTP 요청에 대한 특정 엔드 포인트에 대한 핸들러를 작성하도록 지시합니다. 엔드 포인트는 HTTP 요청 방법 (이 경우 GET) 및 라우트 경로에 해당합니다. 라우트 경로는 무엇입니까? 핸들러의 라우트 경로는 제어기에 선언된 (선택적) 접두부와 요청 데코레이터에 지정된 경로를 연결하여 결정됩니다. 모든 경로에 대한 접두사 (`cats`)를 선언하고 데코레이터에 경로 정보를 추가하지 않았기 때문에 Nest는 `GET/cats` 요청을 이 핸들러에 매핑합니다. 언급 한 바와 같이, 경로에는 선택적 컨트롤러 경로 접두사 **와** 요청 메소드 데코레이터에 선언된 경로 문자열이 모두 포함됩니다. 예를 들어, 데코레이터 `@Get('profile')`과 결합된 `customers`의 경로 접두사는 `GET/customers/profile`과 같은 요청에 대한 경로 매핑을 생성합니다.

위의 예제에서 GET 요청이 이 엔드 포인트에 이루어지면 Nest는 요청을 사용자 정의 `findAll()`메소드로 라우팅합니다. 여기서 선택한 메소드 이름은 완전히 임의적입니다. 경로를 바인딩 할 메소드를 선언해야 하지만 Nest는 선택한 메소드 이름에 아무런 의미도 부여하지 않습니다. 이 메소드는 200 상태 코드 및 연관된 응답 (이 경우 문자열)을 리턴합니다. 왜 그런 일이 발생합니까? 설명하기 위해 먼저 Nest가 응답을 조작하기 위해 두 가지 **다른** 옵션을 사용한다는 개념을 소개합니다.

| 표준 (권장)   | 이 내장 메소드를 사용하여 요청 핸들러가 JavaScript 오브젝트 또는 배열을 리턴하면 **자동으로** JSON으로 직렬화됩니다. 그러나 문자열을 반환하면 Nest는 시도하지 않고 문자열 만 보냅니다. 직렬화하십시오. 따라서 응답 처리가 간단 해집니다. 값을 반환하면 Nest가 나머지를 처리합니다. 또한 201을 사용하는 POST 요청을 제외하고 응답의 **Status code**는 기본적으로 항상 200입니다. `@HttpCode(...)`핸들러 수준의 데코레이터를 추가하여이 동작을 쉽게 변경할 수 있습니다. ([Status codes](https://app.gitbook.com/s/-LpOhNvIYtogx8UUAkWn/overview/controllers#status-code)를 보세요). |
| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 라이브러리별 옵션 | 라이브러리 별 (예: Express) [응답 객체](http://expressjs.com/en/api.html#res)를 사용할 수 있습니다. 메소드 핸들러 서명의 `@Res()` 데코레이터 (예: `findAll(@Res() response)`)를 사용하여 삽입할 수 있습니다. 이 접근 방식을 사용하면 해당 객체에 의해 노출된 기본 응답 처리 방법을 사용할 수 있습니다 (및 책임). 예를 들어 Express를 사용하면 `response.status(200).send ()`와 같은 코드를 사용하여 응답을 구성 할 수 있습니다.                                                                                                  |

> warning **경고** 두 가지 방법을 동시에 사용할 수는 없습니다. Nest는 핸들러가 `@Res()` 또는 `@Next()`를 사용하는 시기를 감지하여 라이브러리별 옵션을 선택했음을 나타냅니다. 두 방법을 동시에 사용하는 경우 이 단일 경로에 대해 표준 방법이 **자동으로 비활성화** 되어 더 이상 예상대로 작동하지 않습니다.

## Request object

핸들러는 종종 클라이언트 **요청** 세부 사항에 액세스해야합니다. Nest는 기본 플랫폼의 [요청 객체](http://expressjs.com/en/api.html#req)에 대한 액세스를 제공합니다 (기본적으로 Express). 처리기의 서명에 `@Req()` 데코레이터를 추가하여 Nest에게 요청하도록 요청 객체에 액세스 할 수 있습니다.

```typescript
@@filename(cats.controller)
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';
  }
}
@@switch
import { Controller, Bind, Get, Req } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  @Get()
  @Bind(Req())
  findAll(request) {
    return 'This action returns all cats';
  }
}
```

> info **힌트** `express` 타이핑을 이용하려면 (위의 `request: Request` 파라미터 예제와 같이) `@types/express` 패키지를 설치하십시오.

요청 개체는 HTTP 요청을 나타내며 요청 쿼리 문자열, 매개 변수, HTTP 헤더 및 본문에 대한 속성을 갖습니다 (더 자세한 내용은 [여기](http://expressjs.com/en/api.html#req)). 대부분의 경우 이러한 속성을 수동으로 가져올 필요는 없습니다. `@Body()` 또는 `@Query()`와 같은 전용 데코레이터를 대신 사용할 수 있습니다. 아래는 제공된 데코레이터와 이들이 나타내는 일반 플랫폼 별 오브젝트 목록입니다.

| `@Request()`              | `req`                               |
| ------------------------- | ----------------------------------- |
| `@Response()`             | `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]` |

\*위의 **라이브러리 별** 섹션에서 언급했듯이 `Response` 객체에는 두 가지 종류가 있습니다. *standard* one은`@Response()` 데코레이터로 액세스합니다. `@Res()` 데코레이터를 사용하여 기본 네이티브 플랫폼 `Response`객체에 액세스 할 수 있습니다. 해당 섹션을 검토하여 차이점을 이해하십시오.

> info **힌트** 나만의 커스텀 데코레이터를 만드는 방법을 배우려면 [여기](https://app.gitbook.com/custom-decorators) 장을 방문하십시오.

## Resources

이전에는 Cats 자원을 가져 오는 엔드 포인트를 정의했습니다 (**GET** 경로). 또한 일반적으로 새 레코드를 작성하는 엔드 포인트를 제공하려고합니다. 이를 위해 **POST** 핸들러를 만듭니다.

```typescript
@@filename(cats.controller)
import { Controller, Get, Post } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  @Post()
  create(): string {
    return 'This action adds a new cat';
  }

  @Get()
  findAll(): string {
    return 'This action returns all cats';
  }
}
@@switch
import { Controller, Get, Post } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  @Post()
  create() {
    return 'This action adds a new cat';
  }

  @Get()
  findAll() {
    return 'This action returns all cats';
  }
}
```

그렇게 간단합니다. Nest는 나머지 표준 HTTP 요청 엔드 포인트 데코레이터를 동일한 방식으로 제공합니다 - `@Put()`, `@Delete()`, `@Patch()`, `@Options()`, `@Head()` 및 `@All()` 각각은 해당 HTTP 요청 방법을 나타냅니다.

## Route wildcards

패턴 기반 경로도 지원됩니다. 예를 들어 별표는 와일드 카드로 사용되며 모든 문자 조합과 일치합니다.

```typescript
@Get('ab*cd')
findAll() {
  return 'This route uses a wildcard';
}
```

`'ab*cd'`라우트 경로는 `abcd`, `ab_cd`, `abecd` 등과 일치합니다. `?`, `+`, `*`및 `()`문자는 라우트 경로에 사용될 수 있으며 정규 표현식의 하위 집합입니다. 하이픈 (`-`)과 점 (`.`)은 문자 그대로 문자열 기반 경로로 해석됩니다.

## Status code

언급 한대로 **Status Code**라는 응답은 **201** 인 POST 요청을 제외하고 기본적으로 항상 **200**입니다. 핸들러 레벨에서 `@HttpCode(...)`데코레이터를 추가하여이 동작을 쉽게 변경할 수 있습니다.

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

상태 코드는 정적이지 않지만 다양한 요인에 따라 달라집니다. 이 경우, 라이브러리 특정 **Response**을 사용할 수 있습니다 ( `@Res()` 객체를 사용하여 주입) (또는 오류가 발생한 경우 예외 발생).

## Headers

커스텀 응답 헤더를 지정하기 위해 `@Header()`데코레이터 또는 라이브러리 특정 응답 객체를 사용하고`res.header()`를 직접 호출 할 수 있습니다.

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

## Route parameters

정적 경로가있는 경로는 요청의 일부로 **동적 데이터**를 수락해야하는 경우 작동하지 않습니다 (예: `GET /cats/1)`를 사용하여 ID가 `1` 인 Cat을 가져옵니다. 매개 변수로 경로를 정의하기 위해 라우트 경로에 경로 매개 변수 **토큰**을 추가하여 요청 URL의 해당 위치에서 동적 값을 캡처 할 수 있습니다. 아래의 `@Get()`데코레이터 예제에서 경로 매개 변수 토큰은 이 사용법을 보여줍니다. 이 방법으로 선언 된 경로 매개 변수는 메소드 서명에 추가되어야 하는 `@Param()`데코레이터를 사용하여 액세스 할 수 있습니다.

```typescript
@@filename()
@Get(':id')
findOne(@Param() params): string {
  console.log(params.id);
  return `This action returns a #${params.id} cat`;
}
@@switch
@Get(':id')
@Bind(Param())
findOne(params) {
  console.log(params.id);
  return `This action returns a #${params.id} cat`;
}
```

`@Param()`은 메소드 매개 변수 (위의 예제에서 `params`)를 장식하는 데 사용되며 **route** 매개 변수를 메소드 본문 내에서 장식 된 메소드 매개 변수의 특성으로 사용 가능하게 합니다. 위 코드에서 알 수 있듯이 `params.id`를 참조하여 `id` 매개 변수에 액세스 할 수 있습니다. 특정 매개 변수 토큰을 데코레이터에 전달한 다음 메서드 본문에서 이름으로 직접 경로 매개 변수를 참조 할 수도 있습니다.

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

## Routes order

경로 등록 **순서** (각 경로의 방법이 클래스에 표시되는 순서)가 중요합니다. 식별자 (`cats/:id`)로 Cat를 반환하는 경로가 있다고 가정합니다. 모든 cats를 한 번에 (`cats`) 리턴하는 클래스 정의에서 다른 엔드 포인트를 **아래에** 등록하면 , `GET /cats` 요청은 모든 경로 매개 변수가 선택적이므로 원하는 두 번째 핸들러에 절대 도달하지 않습니다. 다음 예를 참조하십시오.

```typescript
@Controller('cats')
export class CatsController {
  @Get(':id')
  findOne(@Param('id') id: string) {
    return `This action returns a #${id} cat`;
  }

  @Get()
  findAll() {
    // This endpoint will never get called
    // because the "/cats" request is going
    // to be captured by the "/cats/:id" route handler
  }
}
```

이러한 부작용을 피하려면 `findAll()`선언 (데코레이터 포함)을 `findOne()`위로 옮기십시오.

## Scopes

다른 프로그래밍 언어 배경을 가진 사람들의 경우 Nest에서 거의 모든 것이 들어오는 요청에서 공유된다는 것을 배우는 것은 예상치 못한 일입니다. 우리는 데이터베이스에 대한 연결 풀, 전역 상태를 가진 싱글 톤 서비스 등을 가지고 있습니다. Node.js는 모든 요청이 별도의 스레드에 의해 처리되는 요청/응답 다중 스레드 상태 비 저장 모델을 따르지 않습니다. 따라서 싱글 톤 인스턴스를 사용하는 것은 애플리케이션에 **안전**합니다.

그러나 컨트롤러의 요청 기반 수명이 원하는 동작, 예를 들어 GraphQL 애플리케이션의 요청 별 캐싱, 요청 추적 또는 다중 테넌시가 될 수있는 경우가 있습니다. [여기](https://app.gitbook.com/fundamentals/injection-scopes) 범위를 제어하는 방법에 대해 알아보십시오.

## Asynchronicity

우리는 현대 JavaScript를 좋아하며 데이터 추출이 대부분 **비동기**라는 것을 알고 있습니다. 이것이 Nest가 `async`기능을 지원하고 잘 작동하는 이유입니다.

> info **힌트** `async / await` 기능에 대해 자세히 알아보기 [여기](https://kamilmysliwiec.com/typescript-2-1-introduction-async-await)

모든 비동기 함수는 `Promise`를 반환해야 합니다. 즉, Nest가 자체적으로 해결할 수 있는 지연된 값을 리턴 할 수 있습니다. 이것의 예를 보겠습니다:

```typescript
@@filename(cats.controller)
@Get()
async findAll(): Promise<any[]> {
  return [];
}
@@switch
@Get()
async findAll() {
  return [];
}
```

위의 코드는 완전히 유효합니다. 또한 Nest 경로 처리기는 RxJS [관측 가능한 스트림](http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html)을 반환할 수 있어 훨씬 강력합니다. Nest는 아래의 소스를 자동으로 구독하고 마지막으로 방출된 값을 취합니다 (스트림이 완료되면).

```typescript
@@filename(cats.controller)
@Get()
findAll(): Observable<any[]> {
  return of([]);
}
@@switch
@Get()
findAll() {
  return of([]);
}
```

위의 두 가지 방법 모두 작동하며 요구 사항에 맞는 것을 사용할 수 있습니다.

## Request payloads

POST 경로 처리기의 이전 예에서는 클라이언트 매개 변수를 허용하지 않았습니다. 여기에 `@Body()` 데코레이터를 추가하여 이 문제를 해결하겠습니다.

그러나 먼저 (TypeScript를 사용하는 경우) **DTO** (데이터 전송 개체) 스키마를 결정해야 합니다. DTO는 네트워크를 통해 데이터가 전송되는 방식을 정의하는 개체입니다. **TypeScript** 인터페이스를 사용하거나 간단한 클래스를 사용하여 DTO 스키마를 결정할 수 있습니다. 흥미롭게도 여기서 **클래스** 를 사용하는 것이 좋습니다. 왜? 클래스는 JavaScript ES6 표준의 일부이므로 컴파일 된 JavaScript에서 실제 엔티티로 유지됩니다. 반면, 변환 과정에서 TypeScript 인터페이스가 제거되므로 Nest는 런타임시 인터페이스를 참조 할 수 없습니다. **파이프** 와 같은 기능은 런타임에 변수의 메타 타입에 액세스 할 때 추가 가능성을 가능하게 하기 때문에 중요합니다.

`CreateCatDto` 클래스를 만들어 봅시다 :

```typescript
@@filename(create-cat.dto)
export class CreateCatDto {
  readonly name: string;
  readonly age: number;
  readonly breed: string;
}
```

세 가지 기본 속성만 있습니다. 그 후에 우리는 `CatsController` 안에서 새로 생성된 DTO를 사용할 수 있습니다:

```typescript
@@filename(cats.controller)
@Post()
async create(@Body() createCatDto: CreateCatDto) {
  return 'This action adds a new cat';
}
@@switch
@Post()
@Bind(Body())
async create(createCatDto) {
  return 'This action adds a new cat';
}
```

## Handling errors

오류 처리 (예: 예외 작업) [여기](https://app.gitbook.com/exception-filters)에 대한 별도의 장이 있습니다.

## Full resource sample

아래는 사용 가능한 여러 데코레이터를 사용하여 기본 컨트롤러를 만드는 예입니다. 이 컨트롤러는 내부 데이터에 액세스하고 조작하는 몇 가지 방법을 제공합니다.

```typescript
@@filename(cats.controller)
import { Controller, Get, Query, Post, Body, Put, Param, Delete } from '@nestjs/common';
import { CreateCatDto, UpdateCatDto, ListAllEntities } from './dto';

@Controller('cats')
export class CatsController {
  @Post()
  create(@Body() createCatDto: CreateCatDto) {
    return 'This action adds a new cat';
  }

  @Get()
  findAll(@Query() query: ListAllEntities) {
    return `This action returns all cats (limit: ${query.limit} items)`;
  }

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

  @Put(':id')
  update(@Param('id') id: string, @Body() updateCatDto: UpdateCatDto) {
    return `This action updates a #${id} cat`;
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return `This action removes a #${id} cat`;
  }
}
@@switch
import { Controller, Get, Query, Post, Body, Put, Param, Delete } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  @Post()
  @Bind(Body())
  create(@Body() createCatDto) {
    return 'This action adds a new cat';
  }

  @Get()
  @Bind(Query())
  findAll(@Query() query) {
    return `This action returns all cats (limit: ${query.limit} items)`;
  }

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

  @Put(':id')
  @Bind(Param('id'), Body())
  update(@Param('id') id, @Body() updateCatDto) {
    return `This action updates a #${id} cat`;
  }

  @Delete(':id')
  @Bind(Param('id'))
  remove(@Param('id') id) {
    return `This action removes a #${id} cat`;
  }
}
```

## Getting up and running

위의 컨트롤러가 완전히 정의된 상태에서 Nest는 여전히 `CatsController`가 존재한다는 것을 알지 못하므로 결과적으로 이 클래스의 인스턴스를 만들지 않습니다.

컨트롤러는 항상 모듈에 속하므로 `@Module()` 데코레이터 내에 `컨트롤러` 배열을 포함시킵니다. 루트`AppModule`을 제외한 다른 모듈은 아직 정의하지 않았으므로 이를 사용하여 `CatsController`를 소개합니다.

```typescript
@@filename(app.module)
import { Module } from '@nestjs/common';
import { CatsController } from './cats/cats.controller';

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

우리는`@Module()`데코레이터를 사용하여 메타 데이터를 모듈 클래스에 첨부했으며 Nest는 이제 어떤 컨트롤러를 마운트해야 하는지 쉽게 반영 할 수 있습니다.

## Appendix: Library-specific approach

지금까지 우리는 Nest 표준 응답 조작 방법에 대해 설명했습니다. 응답을 조작하는 두 번째 방법은 라이브러리 별 [응답 객체](http://expressjs.com/en/api.html#res)를 사용하는 것입니다. 특정 응답 객체를 주입하려면 `@Res()` 데코레이터를 사용해야 합니다. 차이점을 보여주기 위해 `CatsController`를 다음과 같이 다시 작성해 봅시다 :

```typescript
@@filename()
import { Controller, Get, Post, Res, HttpStatus } from '@nestjs/common';
import { Response } from 'express';

@Controller('cats')
export class CatsController {
  @Post()
  create(@Res() res: Response) {
    res.status(HttpStatus.CREATED).send();
  }

  @Get()
  findAll(@Res() res: Response) {
     res.status(HttpStatus.OK).json([]);
  }
}
@@switch
import { Controller, Get, Post, Bind, Res, Body, HttpStatus } from '@nestjs/common';

@Controller('cats')
export class CatsController {
  @Post()
  @Bind(Res(), Body())
  create(res, createCatDto) {
    res.status(HttpStatus.CREATED).send();
  }

  @Get()
  @Bind(Res())
  findAll(res) {
     res.status(HttpStatus.OK).json([]);
  }
}
```

이 방법은 효과가 있으며 실제로 응답 객체 (헤더 조작, 라이브러리 별 기능 등)를 완벽하게 제어하여 더 많은 유연성을 허용하지만 주의해서 사용해야합니다. 일반적으로 이 접근 방식은 훨씬 덜 명확하며 몇 가지 단점이 있습니다. 주요 단점은 인터셉터 및 `@HttpCode()`데코레이터와 같은 Nest 표준 응답 처리에 의존하는 Nest 기능과의 호환성이 손실된다는 것입니다. 또한 코드는 플랫폼에 따라 달라지며 (기본 라이브러리는 응답 객체에 대해 다른 API를 가질 수 있음) 테스트하기가 더 어렵습니다 (응답 객체를 속여야 함).

결과적으로 가능한 경우 Nest 표준 접근 방식이 항상 선호됩니다.
