[NestJS] 10. 커스텀 데코레이터

2022. 10. 1. 13:35· Node.js/NestJS
목차
  1. 커스텀 라우트 데코레이터
  2. 파라미터 데코레이터
  3. 데이터 전달
  4. 파이프와 함께 사용하기
  5. 데코레이터 구성

커스텀 라우트 데코레이터

Nest는 데코레이터로 불리는 언어 기능으로 구축되었습니다. 데코레이터는 프로그래밍 언어에서 흔히 사용되는 잘 알려진 개념입니다. 그러나 자바스크립트 세계에서는 상대적으로 새롭습니다.

파라미터 데코레이터

Nest는 HTTP 라우트 핸들러와 함께 사용할 수 있는 유용한 파라미터 데코레이터를 제공합니다. 아래의 리스트는 데코레이터와 데코레이터가 표현하는 일반 Express 객체입니다.

 

더보기
@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

추가적으로, 직접 데코레이터를 생성할 수 있습니다.

 

Node.js 세계에서 응답 객체에 프로퍼티를 연결하는 것은 흔한 방법입니다. 그러면, 아래와 같은 코드를 사용하여 각 라우트 핸들러에서 객체의 속성을 추적할 수 있습니다.

const user = req.user;

코드를 조금 더 가독성있고 명확하게 작성하기 위해서 @User() 데코레이터를 생성하고 모든 컨트롤러에 재사용할 수 있습니다.

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

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);
}

데이터 전달

데코레이터의 동작이 몇몇 조건에 의해 달라질 때,  data 매개변수를 사용해 데코레이터의 팩토리 함수에 인수를 전달할 수 있습니다. 이에 대한 사례는 요청 객체를 키를 사용하여 프로퍼티들을 추적하는 사용자 정의 데코레이터입니다. 예를 들어, 인증 계층이 요청이 유효한지 검사하고, 유저 엔티티를 요청 객체에 연결시킨다고 가정해봅시다. 인증된 요청에 대한 유저 엔티티는 다음과 같을 것입니다.

{
  "id": 101,
  "firstName": "Alan",
  "lastName": "Turing",
  "email": "alan@email.com",
  "roles": ["admin"]
}

프로퍼티의 이름을 키로 취하고, 만약 키가 존재한다면 관련된 값을 반환하는 데코레이터를 정의해봅시다(만약 존재하지 않거나, 유저 객체가 생성되지 않았다면 undefined를 반환합니다).

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

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

    return data ? user?.[data] : user;
  },
);

컨트롤러에서 @User() 데코레이터를 통해 특정 프로퍼티에 접근하는 방법입니다.

@Get()
async findOne(@User('firstName') firstName: string) {
  console.log(`Hello ${firstName}`);
}

다른 프로퍼티에 대한 다른 키를 통해 이 데코레이터를 사용할 수도 있습니다. 만약 유저 객체가 복잡하다면, 요청 핸들러의 구현을 조금 더 쉽고 가독성있게 만들 수 있습니다.

더보기

타입스크립트 유저의 경우, createParamDecorator<T>()는 일반적인 사용방법입니다. 예를 들어, createParamDecorator<string>((data, ctx) => ...)에서 명시적으로 타입 안전성을 증진시킬 수 있다는 것을 의미합니다. 다른 방법으로는, 팩토리 함수에서 파라미터 타입을 구체적으로 작성할 수도 있습니다(createParamDecorator((data: string, ctx) => ...). 만약 둘을 생략한다면, data 타입은 any가 될 것입니다.

파이프와 함께 사용하기

Nest는 사용자 정의 파라미터 데코레이터를 내장 데코레이터(@Body(), @Param(), @Query())와 같은 방식으로 처리합니다. 즉, 커스텀 파라미터(여기에서는 user 인수)에 대해서도 파이프가 사용됩니다. 게다가, 파이프를 직접 사용자 정의 데코레이터에 적용할 수 있습니다.

@Get()
async findOne(
  @User(new ValidataionPipe({ validateCustomDecorators: true }))
  user: UserEntity,
) {
  console.log(user);
}

validateCustomDecorators 옵션은 반드시 true로 설정되어야 합니다. ValidationPipe는 기본적으로 사용자 정의 데코레이터 인수의 유효성을 검사하지 않기 때문입니다.

데코레이터 구성

Nest는 여러 개의 데코레이터를 구성하는 헬퍼 메서드를 제공합니다. 예를 들어, 인증과 관련된 모든 데코레이터를 하나의 데코레이터에 혼합한다고 가정해봅시다.

 

먼저 @nestjs/swagger를 먼저 설치하겠습니다.

npm i @nestjs/swagger
import {
  applyDecorators,
  SetMetadata,
  UseGuards,
} from '@nestjs/common/decorators';
import { ApiBearerAuth, ApiUnauthorizedResponse } from '@nestjs/swagger';
import { AuthGuard } from '../guards/auth.guard';
import { RolesGuard } from '../guards/roles.guard';

export function Auth(...roles: string[]) {
  return applyDecorators(
    SetMetadata('roles', roles),
    UseGuards(AuthGuard, RolesGuard),
    ApiBearerAuth(),
    ApiUnauthorizedResponse({ description: 'Unauthorized' }),
  );
}

이제 이 사용자 정의 @Auth() 데코레이터를 사용할 수 있습니다.

@Get('users')
@Auth('admin')
findAllUsers() {}

한 번의 선언으로 네 개의 데코레이터를 사용하는 효과를 가집니다.

저작자표시 비영리 (새창열림)

'Node.js > NestJS' 카테고리의 다른 글

[NestJS] 12. 비동기 프로바이더  (0) 2022.10.02
[NestJS] 11. 커스텀 프로바이더  (0) 2022.10.02
[NestJS] 9. 인터셉터  (1) 2022.10.01
[NestJS] 8. 가드  (0) 2022.09.30
[NestJS] 7. 파이프  (0) 2022.09.29
  1. 커스텀 라우트 데코레이터
  2. 파라미터 데코레이터
  3. 데이터 전달
  4. 파이프와 함께 사용하기
  5. 데코레이터 구성
'Node.js/NestJS' 카테고리의 다른 글
  • [NestJS] 12. 비동기 프로바이더
  • [NestJS] 11. 커스텀 프로바이더
  • [NestJS] 9. 인터셉터
  • [NestJS] 8. 가드
턴태
턴태
import { Dream } from "future";
턴태
턴태의 밑바닥부터 시작하는 de-vlog
턴태
전체
오늘
어제
  • ROOT (187)
    • Node.js (37)
      • ES6 (1)
      • TypeScript (3)
      • Express.js (16)
      • NestJS (16)
      • JS (24)
    • 프론트엔드 (29)
      • CS (5)
    • 백엔드 (1)
      • 검색 (2)
      • Database (1)
    • 기타 툴 (1)
      • git (1)
    • 데브옵스 & 인프라 (19)
      • Kubernetes (15)
      • Docker (2)
      • Monitoring (1)
      • IaC (1)
    • Algorithm (90)
      • Implementation & simulation (5)
      • Math (4)
      • Brute Force (1)
      • String (0)
      • Graph (5)
      • Recursion & Backtracking (19)
      • Divide & Conquer (2)
      • Dynamic Programming (18)
      • Greedy (13)
      • Priority Queue (2)
      • Binary Search (6)
      • Data Structure (7)
      • Shortest Path (5)
      • Minimum Spanning Tree (1)
      • Sorting (1)
      • Prefix Sum (1)
    • Linux (1)
      • Ubuntu (1)
    • Diary (5)
      • Algorithm (1)
      • Conference (1)
      • Retrospective (3)
    • Book (0)
      • Self-Development (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • Omuk
  • 백준
  • 네스트
  • dynamic programming
  • N과 M
  • 함수형 프로그래밍
  • GREEDY
  • baekjoon
  • 파이썬
  • python
  • Kubernetes
  • 자바스크립트
  • 다이나믹 프로그래밍
  • 토이프로젝트
  • 인프런
  • nestjs
  • 익스프레스
  • Express
  • Toy Project
  • 타입스크립트
  • k8s
  • 인프런X디프만
  • 백트래킹
  • 노드
  • backtracking
  • 쿠버네티스
  • 오먹
  • node.js
  • 디프만
  • TypeScript

최근 댓글

최근 글

hELLO · Designed By 정상우.v4.2.1
턴태
[NestJS] 10. 커스텀 데코레이터
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.