[NestJS docs] Custom decorators

nakkim·2022년 7월 18일
0

NestJS docs

목록 보기
7/10
post-custom-banner

https://docs.nestjs.com/custom-decorators

Custom route decorators

Param decorators

Nest가 제공하는 HTTP 라우트 핸들러와 함께 사용할 수 있는 param decorators

데코레이터파라미터
@Request(), @Req()req
@Response(), @Res()res
@Next()next
@Session()req.session
@Param(param?: string)req.params / req.params[param]
@Body(param?: string)req.body / req.body[param]
@Query(param?: string)req.query / req.query[param]
@Headers(param?: string)req.headers / req.headers[param]
@Ip()req.ip
@HostParam()req.hosts

그래서 데코레이터가 뭐가 좋은디??

express에서 Request 객체의 유저 프로퍼티를 가져오려면 아래와 같이 해야 한다.

const user = req.user;

이렇게 하는 대신, req.user를 반환하는 @User() 데코레이터를 만들어서 모든 컨트롤러에서 재사용할 수가 있다.

import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const User = createParamDecorator(
  (data: unknown, ctx: ExecutionContext) => {
    const request = ctx.switchToHttp().getRequest();
    return request.user;
  },
);
@Get()
async findOne(@User() user: UserEntity) {
  console.log(user);
}

짱~

Passing data

일부 조건에 따라 데코레이터 동작을 다르게 하고 싶으면 매개변수를 이용하면 된다. 예제로 배워봅시다.

예시: Request 객체에서 키별로 프로퍼티를 추출하는 커스텀 데코레이터

아래는 유저 엔티티

{
  "id": 101,
  "firstName": "Alan",
  "lastName": "Turing",
  "email": "alan@email.com",
  "roles": ["admin"]
}
import { createParamDecorator, ExecutionContext } from '@nestjs/common';

export const User = createParamDecorator(
  (data: string, ctx: ExecutionContext) => {
    const request = ctx.switchToHttp().getRequest();
    const user = request.user;

    return data ? user?.[data] : user;
  },
);
@Get()
async findOne(@User('firstName') firstName: string) {
  console.log(`Hello ${firstName}`);
}

참 쉽죠? 딱히 달만한 사족이 없다..

타입스크립트를 사용하나요?
createParamDecorator<T>() 는 제네릭이다. createParamDecorator<string>((data, ctx => ...) 처럼 data의 타입을 지정할 수 있음. 또는, 팩토리 함수에 매개변수 타입을 지정할 수도 있다. createParamDecorator((data: string, ctx) => ...)
둘 다 생략할 경우 데이터 타입은 any가 됨..


Working with pipes

Nest는 커스텀 param decorator를 빌트인 데코레이터와 똑같이 취급한다. 따라서 파이프를 적용할 수 있음

@Get()
async findOne(
	// 디폴트는 커스텀을 검증하지 않기 때문에 true로 해줘야함
  @User(new ValidationPipe({ validateCustomDecorators: true }))
  user: UserEntity,
) {
  console.log(user);
}

Decorator composition

여러 데코레이터를 묶을 수 있는 메서드가 있다.

예를 들어, 인증과 관련 데코레이터를 하나의 데코레이터로 묶는다고 치자.

다음과 같이 할 수 있음

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

export function Auth(...roles: Role[]) {
  return applyDecorators(
    SetMetadata('roles', roles),
    UseGuards(AuthGuard, RolesGuard),
    ApiBearerAuth(),
    ApiUnauthorizedResponse({ description: 'Unauthorized' }),
  );
}
@Get('users')
@Auth('admin')
findAllUsers() {}

이렇게 쓰면댐 멋지지~?

@nestjs/swagger@ApiHideProperty() 데코레이터는 묶을 수 없음.
applyDecorators 함수 적용 불가능

profile
nakkim.hashnode.dev로 이사합니다
post-custom-banner

0개의 댓글