데코레이터란?

데코레이터는 대다수의 프로그래밍 언어에 사용되는 잘 알려진 개념이지만 JavaScript 세계에서는 도입된지 얼마되지 않은 개념이라고 합니다.

데코레이터에 대해 공식 문서에서는 이렇게 정의하고 있습니다.

An ES2016 decorator is an expression which returns a function and can take a target, name and property descriptor as arguments. You apply it by prefixing the decorator with an @ character and placing this at the very top of what you are trying to decorate. Decorators can be defined for either a class, a method or a property.

데코레이터는 함수를 반환하며 인자로는 타겟, 이름, 프로퍼티 설명자를 가지는 표현식입니다.

데코레이터 앞에 @ 문자를 붙여 사용하면 되며, 이는 데코레이트하고자 하는 클래스, 메서드, 프로퍼티의 최상단에 위치시켜 줍니다.

데코레이터는 함수에서 코드를 바꾸지 않고 추가하거나 수정하고 싶을 때 사용하는 문법입니다.

데코레이터 실제 사용 예시

- 로그 남기기

- 접근 제어와 인증 처리

- API 로직 처리 시간 측정

- API 호출 수 제한

- 캐싱

데코레이터를 사용하는 이유?

기존에 만들어진 함수가 다른 곳에서 이미 많이 사용되고 있을 때 (= 함수 코드의 변경이 어려운 경우) 코드를 변경하지 않고, 필요한 내용을 추가하거나 수정하고 싶을 때 사용합니다.

// 컨트롤러 1 동작 흐름
A -> C -> D -> G
// 컨트롤러 2 동작 흐름
A -> B -> G
// 컨트롤러 3 동작 흐름
A -> E -> F -> C -> G

각 컨트롤러 별 동작 흐름을 살펴보면 공통적으로 포함되어 사용되는 AG 가 있습니다.

DRY(Don't Repeat Yourself) 원칙에 따라 A와 G가 포함된 함수를 별도로 선언하고 사용되면 좋겠다고 느껴질 것입니다.

데코레이터는 코드의 중복을 제거해 코드의 재사용성을 높이기 위해 사용한다고 이해할 수 있습니다.

NestJS 에 존재하는 데코레이터

NestJS 에는 많은 데코레이터가 존재합니다.

대표적으로, @Body(), @Param(), @Query() 등 데코레이터를 통해 특정 요청에 대한 값을 가져올 수 있습니다.

예를 들어, 리퀘스트 바디 값을 가져오기 위해서는 이렇게 작성합니다.

Express 라면,

const data = req.body;

하지만 NestJS 에서는 좀 더 가독성을 높이고 req 에 대한 의존도를 줄이기 위해 @Body() 데코레이터를 사용할 수 있습니다.

joinUser(@Body('user') joinUserDto: JoinUserDto)

이런 식으로 req.body 안에 있는 user 의 값을 joinUserDto 라는 변수에 쉽게 저장할 수 있습니다.

커스텀 데코레이터

위에서 설명한 데코레이터를 커스텀하여 사용할 수 있습니다.

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

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

@nestjs/common 으로부터 createParamDecorator 를 사용하여 커스텀 데코레이터를 만들어주면 됩니다.

그리고 ctx.switchToHttp().getRequest(); 를 통해 request 에 접근할 수 있습니다.

참고) ExecutionContext 타입의 ctx 에 대하여
커스텀 데코레이터를 생성할 때 사용하는 createParamDecorator 함수에 인자로 들어가는 콜백 함수 안에서 ExecutionContext 타입의 ctx 를 통해 동시에 http, websocket, rpc 프로토콜 정보를 가져올 수 있습니다.

ctx 변수에는 현재 데코레이터가 어떤 환경에서 실행되고 있는지에 대한 정보가 컨텍스트 안에 들어 있습니다.

위 함수는 request 로부터 user 데이터만을 전달하는 데코레이터입니다.

 

방금 만든 데코레이터를 컨트롤러에 적용하면 다음과 같습니다.

@Post()
joinUser(@User() user) {
  console.log(user);
}

user 데코레이터를 만들어 두니 req.user 정보가 필요한 모든 컨트롤러에 적용 가능해서 코드 재사용성을 높일 수 있어서 좋습니다.

게다가 컨트롤러의 request 에 대한 의존성을 없애주어 테스트가 용이하게 되어 좋습니다.

정리

이번 시간을 통해 데코레이터가 무엇이고 언제 사용되고 왜 쓰이는지와 NestJS 에서 제공되는 데코레이터들, 커스텀 데코레이터를 만드는 방법에 대해 알아보았습니다.

이번 시간에 소개한 데코레이터들 외에 다양한 데코레이터가 있으니 자세한 사용방법은 nest js 공식문서를 참고해주시면 될 것 같습니다.

출처

https://www.inflearn.com/course/%EC%8A%AC%EB%9E%99%ED%81%B4%EB%A1%A0%EC%BD%94%EB%94%A9-%EB%B0%B1%EC%97%94%EB%93%9C 

https://devkhk.tistory.com/23 

 

[python] decorator 파이썬 데코레이터 이해하기

데코레이터는 함수에서 코드를 바꾸지 않고 추가하거나 수정하고 싶을 때 사용하는 문법이다. 처음 이해하기 조금 난해할 수 있지만 사용 이유, 단순하게 이해할 수 있는 순서 그리고 현실적인

devkhk.tistory.com

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

 

Documentation | NestJS - A progressive Node.js framework

Nest is a framework for building efficient, scalable Node.js server-side applications. It uses progressive JavaScript, is built with TypeScript and combines elements of OOP (Object Oriented Progamming), FP (Functional Programming), and FRP (Functional Reac

docs.nestjs.com

 

'라이브러리 & 프레임워크 > NestJS' 카테고리의 다른 글

Exception filter  (0) 2022.11.28
Validation  (0) 2022.11.28
Mapped Types  (0) 2022.11.28
[TypeORM] 마이그레이션  (0) 2022.11.27
[TypeORM] TypeORM 엔티티 상속을 통한 중복 코드 제거  (0) 2022.11.26
복사했습니다!