https://docs.nestjs.com/custom-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);
}
짱~
일부 조건에 따라 데코레이터 동작을 다르게 하고 싶으면 매개변수를 이용하면 된다. 예제로 배워봅시다.
예시: 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가 됨..
Nest는 커스텀 param decorator를 빌트인 데코레이터와 똑같이 취급한다. 따라서 파이프를 적용할 수 있음
@Get()
async findOne(
// 디폴트는 커스텀을 검증하지 않기 때문에 true로 해줘야함
@User(new ValidationPipe({ validateCustomDecorators: true }))
user: UserEntity,
) {
console.log(user);
}
여러 데코레이터를 묶을 수 있는 메서드가 있다.
예를 들어, 인증과 관련 데코레이터를 하나의 데코레이터로 묶는다고 치자.
다음과 같이 할 수 있음
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 함수 적용 불가능