Reflect-metadata

reflect-metadata란

TypeScript(or JS)에서 데코레이터를 활용하여 메타데이터를 관리하기 위해 사용되는 라이브러리

  • 자바스크립트의 Reflact 객체를 이용하여 클래스 또는 함수에 메타데이터를 추가하거나 수정할 수 있게 해줌

  • 데코레이터를 추가하여 런타임 때 코드의 동작을 수정하는것

Metadata → "데이터의 대한 데이터", "어떤 목적을 가지고 만들어진 데이터", "데이터의 추가 정보"

즉, 메타데이터는 타입스크립트 데코레이터를 통해 추가된 클래스, 메서드, 프로퍼티의 부가적인 정보를 의미한다.

Reflect

ES6에서 도입된 내장 객체

리플렉션은 코드가 실행되는 동안 스스로 검사하고 수정할 수 있는 기능

자바스크립트에서 메타프로그래밍을 할 때 사용 된다.

메타데이터 추가

key: value 구조의 메타데이터 추가

metadataKey에 식별되므로 원하는 만큼 메타데이터를 추가할 수 있다.

Reflect.defineMetadata(metadataKey, metadataValue, target);

REflect.defineMetadata(metadataKey, metadataValue, target, propertyKey);

메타데이터 가져오기

대상의 특정 메타데이터 키에 식별되는 메타데이터 값 추출

const meta = Reflect.getMetadata(metadataKey, target);

const meta = Reflect.getMetadata(metadataKey, target, propertyKet);

그 외 다양한 api

// 메타데이터 키가 있는지 확인 -> boolean
const result = Reflect.hasMetadata(metadataKey, target);

// 개체의 정의된 모든 메타데이터의 키 가져오기 -> Array
const metadataKeys = Reflect.getMetadataKeys(target);

// 특정 키의 메타데이터 삭제 -> boolean
const result = Reflect.deleteMetadata(metadataKey, target);

메타 프로그래밍이란?

프로그램이이 자신의 코드를 분석해서 수정하는 방식으로 자기 자신(프로그램)을 다루는 코드를 작성하는 패턴

Decorator(@)

함수 또는 클래스 선언이나 클래스 멤버 위에 추가하는 주석으로, 해당 개체의 동작 방식을 변경하는 함수

타입스크립트 "데코레이터"의 해부학 및 사용 패턴

놀랍게도 TS에만 있는 기능이 아닌 네이티브한 JS 기능(표준화 X)이라고 한다.

@ 접두사를 사용하는 자바스크립트 함수, 전달받은 인자(클래스, 함수)의 동작을 수정하여 반환한다.

즉, 클래스나 함수 위에 배치하면 런타임때 해당 함수, 클래스를 인수로 사용하여 호출되고 전달받은 함수,클래스의 동작을 수정하여 반환한다.

@singleton()
class SingletonClass {
  //...
}

TS에서 데코레이터 기능을 사용하려면 tsconfig.json 데코레이터 관련 옵션을 다음과 같이 추가해주어야 한다.

{
  "compilerOptions": {
    "experimentalDecorators": true, // 데코레이터(실험적인) 사용 여부
    "emitDecoratorMetadata": true, // 데코레이터에서 메타 데이터 추출 가능
  }
}

Reflect.metadata()

Reflect.metadata()는 decorator(@)를 만드는 메서드

내부적으로 데코레이션하는 개체에 메타데이터를 추가하는 Reflect.defineMetadata를 구현한다

@Reflect.metadata(metadataKey, metadataValue)
class DecorationClass {
  @Reflect.metadata(metadataKey, metadataValue)
  decorationMethod(){...}
}

함수로 만들어서 사용

function fooDecorator() {
  return Reflect.metadata('foo', 'bar');
}

@fooDecrator()
class WoongClass { }

Reflect.getMetadata('foo', WoongClass); // 'bar';

Last updated