> 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/graphql/tooling.md).

# Tooling

## Tooling

GraphQL 세계에서 많은 기사는 **인증(authentication)** 또는 **부작용(side-effects)**&#xACFC; 같은 항목을 처리하는 방법에 대해 불평합니다. 비즈니스 로직에 넣어야 합니까? 예를 들어 권한 부여 논리와 같이 쿼리와 뮤테이션을 향상시키기 위해 고차 함수를 사용해야 합니까? 또는 [스키마 지시어](https://www.apollographql.com/docs/apollo-server/v2/features/directives.html)를 사용하십시오. 어쨌든 한가지 답은 없습니다.

Nest 생태계는 [guards](https://app.gitbook.com/%20guards) 및 [interceptors](https://app.gitbook.com/%20interceptors)와 같은 기존 기능을 사용하여 이 문제를 해결하려고 합니다. 그 배후의 아이디어는 중복성을 줄이고 또한 체계적이고 읽기 쉽고 일관성 있는 응용 프로그램을 만드는 데 도움이 되는 도구를 제공하는 것입니다.

## Overview

간단한 REST 애플리케이션에서와 동일한 방식으로 [guards](https://app.gitbook.com/%20guards), [interceptors](https://app.gitbook.com/%20interceptors), [filters](https://app.gitbook.com/%20exception-filters) 또는 [pipes](https://app.gitbook.com/%20pipes)를 사용할 수 있습니다. 또한 [custom decorators](https://app.gitbook.com/%20custom-decorators) 기능을 활용하여 자신만의 데코레이터를 쉽게 만들 수 있습니다. 그들은 모두 동등하게 행동합니다. 다음 코드를 보자.

```typescript
@Query('author')
@UseGuards(AuthGuard)
async getAuthor(@Args('id', ParseIntPipe) id: number) {
  return await this.authorsService.findOneById(id);
}
```

보시다시피 GraphQL은 가드와 파이프 모두에서 잘 작동합니다. 예를 들어 인증 로직을 가드로 이동하거나 REST 애플리케이션에서와 동일한 가드 클래스를 재 사용할 수 있습니다. 인터셉터는 똑같은 방식으로 작동합니다.

```typescript
@Mutation()
@UseInterceptors(EventsInterceptor)
async upvotePost(@Args('postId') postId: number) {
  return await this.postsService.upvoteById({ id: postId });
}
```

## Execution context

그러나 가드와 인터셉터 모두에 의해 수신되는 `ExecutionContext`는 약간 다릅니다. GraphQL 리졸버에는 각각 `root`, `args`, `context` 및 `info`와 같은 별도의 인수 세트가 있습니다. 따라서 주어진 `ExecutionContext`를 `GqlExecutionContext`로 변환해야 합니다. 기본적으로 매우 간단합니다.

```typescript
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { GqlExecutionContext } from '@nestjs/graphql';

@Injectable()
export class AuthGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const ctx = GqlExecutionContext.create(context);
    return true;
  }
}
```

`GqlExecutionContext`는 `getArgs()`, `getContext()`등과 같은 각 인수에 해당하는 메소드를 노출합니다. 이제 현재 처리된 요청에 특정한 모든 인수를 손쉽게 선택할 수 있습니다.

## Exception filters

[예외 필터](https://app.gitbook.com/exception-filters)는 GraphQL 응용 프로그램과도 호환됩니다.

```typescript
@Catch(HttpException)
export class HttpExceptionFilter implements GqlExceptionFilter {
  catch(exception: HttpException, host: ArgumentsHost) {
    const gqlHost = GqlArgumentsHost.create(host);
    return exception;
  }
}
```

> info **힌트** `GqlExceptionFilter`와 `GqlArgumentsHost`는 모두 `@nestjs/graphql` 패키지에서 가져옵니다.

그러나 이 경우 HTTP 앱에서와 같이 기본 `response`객체에 액세스 할 수 없습니다.

## Custom decorators

앞에서 언급했듯이 [custom decorators](https://app.gitbook.com/%20custom-decorators) 기능은 GraphQL 리졸버의 매력처럼 작동합니다. 팩토리 함수는 `response`객체 대신 인수 배열을 사용합니다.

```typescript
export const User = createParamDecorator(
  (data, [root, args, ctx, info]) => ctx.user,
);
```

그리고:

```typescript
@Mutation()
async upvotePost(
  @User() user: UserEntity,
  @Args('postId') postId: number,
) {}
```

> info **힌트** 위의 예에서, `user` 객체가 GraphQL 어플리케이션의 컨텍스트에 할당되었다고 가정했습니다.
