JavaScript & TypeScript

[TS] Decorators

반응형

데코레이터는 아직 확정적으로 사용할 수 없는 기능이기 때문에 변경사항이 일어나면 코드를 수 없이 변경해야 하기 때문에 깊게 사용하지 않는 것이 좋습니다. 데코레이터는 향후 릴리스에서 변경될 수 있는 실험적 기능입니다. 공식문서에서도 명확히 구현되지 않아 문제점에 대해 이야기 하고 있습니다.

그럼에도 불구하고 많은 곳에서 사용하고 있습니다.

(내용은 공식문서에 있는 내용입니다.)

 

Decorators 기능 활성화

Decorators를 활성화하려면 tsconfig.json에서 experimentDecorators compiler options를 true로 설정해야 합니다.

{
  "compilerOptions": {
    "target": "ES5",
    "experimentalDecorators": true
  }
}

 

 

Decorators

사용하는 방법은 선언된 오브젝트 이름에 @을 붙여 사용해 줍니다.

 

어떠한 오브젝트를 구현했을 때 재사용이 가능하게 해줍니다. 데코레이터의 사용되는 방식은 수학 함수의 구성과 유사합니다.

함수 f  g 를 구성할 때 결과 합성( f  g )( x )은 f ( g ( x ))와 같습니다. 따라서 TypeScript의 단일 선언에서 여러 데코레이터를 평가할 때 다음 단계가 수행됩니다.

  1. 각 데코레이터의 표현식은 위에서 아래로 평가됩니다.
  2. 그런 다음 결과는 아래에서 위로 함수로 호출됩니다.
function first() {
  console.log("first(): factory evaluated");
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    console.log("first(): called");
  };
}
 
function second() {
  console.log("second(): factory evaluated");
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    console.log("second(): called");
  };
}
 
 // 데코레이터 사용
class ExampleClass {
  @first()
  @second()
  method() {}
}




// console.log
first(): factory evaluated
second(): factory evaluated
second(): called
first(): called

 

Class Decorator

클래스 선언 직전에 선언됩니다. 클래스 데코레이터는 클래스의 생성자에 적용되며 클래스 정의를 관찰, 수정 또는 대체하는 데 사용할 수 있습니다. 클래스 데코레이터는 선언 파일이나 다른 주변 컨텍스트에서 사용할 수 없습니다.

 

클래스 데코레이터의 표현식은 런타임 시 함수로 호출되며 데코레이트된 클래스의 생성자가 유일한 인수입니다.

클래스 데코레이터가 값을 반환하면 클래스 선언이 제공된 생성자 함수로 바뀝니다.

 

function reportableClassDecorator<T extends { new (...args: any[]): {} }>(constructor: T) {
  return class extends constructor {
    reportingURL = "http://www...";
  };
}
 
@reportableClassDecorator
class BugReport {
  type = "report";
  title: string;
 
  constructor(t: string) {
    this.title = t;
  }
}
 
const bug = new BugReport("Needs dark mode");
console.log(bug.title); // "Needs dark mode"
console.log(bug.type); // "report"
 
// 데코레이터는 TypeScript 유형을 변경하지 않습니다.
// 새로운 property `reportingURL` 은 알지 못합니다.
bug.reportingURL;// error

 

데코레이션은 클래스에 적용되는 과정이 좀 더 간편합니다.

적용될 클래스에 대한 타입정의를 확실하게 함으로써, 비즈니스 로직이 특정 클래스에 최적화된 부품 역할을 수행 하도록 하는 것입니다.

 

데코레이터를 사용한다고 해서 데코레이터와 클래스간의 결합이 아닌 그 자체의 전달이라 생각 됩니다.

그렇게 생각하는 이유는 데코레이터는 동적 컴포지션으로써 런타임시 조합을 함으로, 특정 인스턴스에 필요한 조합이면 동적을 사용하고,

스태틱 컴포지션은 컴파일에서 조합을 하기 때문에 클래스 모든 인스턴스에 필요한 조합이라면 스태틱을 사용하는 것이 맞다고 생각 됩니다.

 

공식문서

https://www.typescriptlang.org/docs/handbook/decorators.html

깃허브

https://github.com/tc39/proposal-decorators

참고링크

https://typescript-kr.github.io/pages/decorators.html

 

 

typeORM이나 NestJS에서 많이 사용하여 궁금한 것이 조금이나마 해소가 되었습니다.

아직 데코레이터가 정확히 표준화가 되지 않았고, 더 추가적인 기능이 있지만 점점 추가해서 써보려 합니다.

반응형

'JavaScript & TypeScript' 카테고리의 다른 글

[node.js] express-validator param error  (0) 2022.03.29
[TS] Compile (option)  (0) 2022.03.22
[TS] utility type  (0) 2022.03.21
[TS] type alias, interface 차이  (0) 2022.03.20
[JS] ProtoType  (0) 2022.03.15