일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 |
- TIL
- html
- bean
- dfs
- nestjs
- logger
- GraphQL
- queue
- REST API
- 인접리스트
- 자료구조
- 인접행렬
- winston
- Spring
- 변수
- 코딩테스트
- java
- OOP
- LifeCycle
- MySQL
- JWT
- Interceptor
- javascript
- node.js
- 탐욕법
- Deep Dive
- 알고리즘
- css
- typescript
- 프로그래머스
- Today
- Total
처음부터 차근차근
[NestJS] Custom decorator 본문
NestJS는 decorator라는 기능으로 구성되어 있습니다.
Decorator는 여러 프로그래밍 언어에서는 많이 알려져있지만, Javascript에서는 생소합니다. 이 부분은 Typescript 에서 자세히 다룹니다.
Param decorators
Nest에서는 Http route handler와 같이 사용할 수 있는 param decorator를 제공합니다.
우리가 만약 Request 객체에서 User를 받아올려고 한다면, @Body() user:userEntity를 사용해야 합니다.
@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 |
그러나 우리는 직접 데코레이터를 만들 수 있습니다.
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);
}
하지만 이렇게 데코레이터를 만들어 적용한다면, 간단하게 구상할 수 있습니다.
(마치 @Body()에 있는 데이터를 받아오는 것입니다.)
Passing Data
이번에는 특정 조건에 따라 다른 처리를 할 수 있도록 하는 데코레이터를 만들어보겠습니다.
우리가 이러한 요청을 받는다고 생각해봅시다.
{
"id": 101,
"firstName": "Alan",
"lastName": "Turing",
"email": "alan@email.com",
"roles": ["admin"]
}
이러한 userEntity가 있을 때, 원하는 속성만 받아올 수 있도록 해보겠습니다.
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}`);
}
해당 data를 통해서 요청 객체의 특정 데이터를 키 값으로 추출할 수 있게 만들었습니다.
위와 같이 @User('firstName') 데코레이터를 통해 request.user.firstName만 추출할 수 있습니다.
typescript 환경에서는 createParamDecorator<T>() 는 generic이기 때문에 data 매개 변수의 타입을 강제할 수 있습니다.
Working with pipes
custom param decorator에는 동일하게 pipe를 적용할 수 있습니다.
다만, custom decorator는 pipe를 적용하기 위해서는 validateCustomDecorators 옵션이 true이어야 합니다.
Decorator composition
데코레이터를 사용하다보면, 수많은 데코레이터를 쌓인 것을 볼 수 있습니다.
하나의 예시로, NestJS를 들으면서 강의 내용을 따라해 본 결과, Decorator가 많이 쌓인 걸 확인할 수 있습니다.
@ApiBearerAuth()
@ApiGetItemsResponse(FindUserResDto)
@Roles(Role.Admin)
@Get()
@UseGuards(JwtAuthGuard)
// 비동기 처리를 위해 Promise로 데이터를 받는다.
async findAll(@Query() { page, size }: PageReqDto): Promise<FindUserResDto[]> {
// 전체 유저수 확인 메서드
// pagenation을 위해 Page Dto로 데이터를 받는다.
const users = await this.userService.findAll(page, size);
return users.map(({ id, email, createdAt }) => {
return { id, email, createdAt: createdAt.toISOString() };
});
}
이러한 부분은 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() {}
참조
'FrameWork > NestJS' 카테고리의 다른 글
[NestJS] NestJS에서 GraphQL 초기 설정 (1) | 2023.11.29 |
---|---|
[NestJS] 제어 역전과 의존성 주입 (1) | 2023.11.29 |
[NestJS] Exception filter (0) | 2023.11.28 |
[NestJS] Pipe (0) | 2023.11.28 |
[NestJS] interceptor (0) | 2023.11.27 |