Nest @데코레이터 부수기#1

InnomDB·2022년 5월 12일
1

데코레이터

  • 데코레이터는 객체가 인스턴스화될 때가 아니라 클래스가 선언될 때 호출됩니다.
  • 동일한 Class/Property/Method/Parameter에 여러 데코레이터를 정의할 수 있습니다.
  • 생성자에는 데코레이터가 허용되지 않습니다.
    참조 - typescript handbook

중요한 포인트
클래스가 선언될 때 호출된다는 것.
프로그램을 실행하면 호출 된다는 것이다.

사진으로 보면

위와 같이 선언부를 다 처리하고 이제 Nest가 start되는 것을 볼 수 있다.

데코레이터들은 마치 합성함수 처럼 동작하는데
각 데코레이터의 표현식은 위에서 아래로 또는 왼쪽에서 오른쪽으로 동작한다.

@deco1
@deco2
title: string

deco1(deco2(title)) 합성 함수처럼 동작한다.
그 이유는 바로 데코레이터가 함수기 때문이다. 함수를 그냥 @뭐 요런식으로 표현한것 뿐이다. 코드 들어가보면 다 함수이다.

나는 여기서 하나 궁금증을 느꼇다.

상황을 살펴보면 내가 만든 커스텀 데코레이터와 속성 데코레이터를 실행할 때였다.
사진으로 살펴보면

@Type이 먼저 그 다음이 @커스텀 데코레이터이다.
참고로 Type 데코레이터는 위쪽에 선언된 데코레이터가 적용된다.
그 이유는 결과는 아래에서 위로 반환하기 때문에 결국 마지막에 반환되는 결과가 Date 타입을 반환하는 데코레이터이기 때문이다.

++) 알아낸 사실

그렇게 반환되는 이유는

메타데이터를 찾을 때 reverse해서 얻어오기 때문에 아래에서 위로 동작된다는 것이다
이것이 의도된 동작인지는 나도 잘 모르겠다.
++) reverse의 reverse인데 왜 그러지.. 이제 봤다. reverse가 2번이네

또한, @Type 데코가 먼저 동작하는 이유는 Nest 자체적인 이유인데

class-transform먼저 실행되고 class-validator가 실행되기 때문에 class-transform인 @Type먼저 실행되는 것이다.

여기서 또 하나 궁금한 것이 생겼는데 class-transform끼리의 우선순위는 어떻게 정해지는지 모르겠다.
@Transfrom / @Type 어째서 @Type이 먼저 실행되는걸까?
아신다면 댓글 부탁드립니다.

합리적 의심)

  private _typeMetadatas = new Map<Function, Map<string, TypeMetadata>>();
  private _transformMetadatas = new Map<Function, Map<string, TransformMetadata[]>>();
  private _exposeMetadatas = new Map<Function, Map<string, ExposeMetadata>>();
  private _excludeMetadatas = new Map<Function, Map<string, ExcludeMetadata>>();

transform을 하려면 type데이터가 필요하니까 typeMetadata먼저 하고 그 다음 transformMeta데이터하고 expose / exclude순이 아닐까 싶다. 그래서 저렇게 생성자를 해놓지 않았을까 의심만 해본다.

하지만 진짜 아리송한것은 실제 값을 넘겨주었을 때 @Type안에 정의해놓았던 console이 나오질 않았다.
클래스 선언 시에는 잘 호출되었다. 그렇다면 커스텀 데코레이터 안에 정의해놓았던 console도 출력이 안되야하는데 커스텀 데코레이터는 console이 너무 잘 찍혔다.

어째서 @Type은 다시 그 함수안으로 들어가질 않고 @커스텀 데코레이터는 들어가는지 이유를 아시는분이 있다면 꼭 댓글 달아주세요 ㅠ..

++) 알아낸 사실
둘 다 들어가지 않는다. 다만 데코레이터 실행 함수로 들어간다.
도대체 @Type(() => { console; return type }에서 인자로 넘기는 함수에서는 console이 찍히는데 왜 다시 @Type을 들어가지 못하는 것일까? 하지만 동작은 잘되서 return type으로 type이 변형된다.

추가)
class-transform 데코레이터들이 동작되는 것은 결국 직렬화 / 역직렬화 과정에서 일어난다.
executor.transform함수를 보면 직렬화 / 역직렬화가 일어날 때에 항상 Type이 먼저 실행되는 것이 코드로 나타나있다.

**번외
데코레이터 팩토리는 꼭 알고 넘어가자

데코레이터 팩토리 (Decorator Factories)
데코레이터가 선언에 적용되는 방식을 원하는 대로 바꾸고 싶다면 데코레이터 팩토리를 작성할 수 있습니다. 데코레이터 팩토리는 단순히 데코레이터가 런타임에 호출할 표현식을 반환하는 함수입니다.

다음과 같은 방식으로 데코레이터 팩토리를 작성할 수 있습니다.

function color(value: string) { // 데코레이터 팩토리
return function (target) { // 데코레이터
// 'target'과 'value' 변수를 가지고 무언가를 수행합니다.
};
}

꼭 위의 링크를 읽어보자!!

profile
이노오오옴

0개의 댓글