# Reflect-metadata

## reflect-metadata란

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

* 자바스크립트의 [Reflact](https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Reflect) 객체를 이용하여 클래스 또는 함수에 메타데이터를 추가하거나 수정할 수 있게 해줌
* 데코레이터를 추가하여 런타임 때 코드의 동작을 수정하는것

{% hint style="info" %}
[**Metadata**](https://ko.wikipedia.org/wiki/%EB%A9%94%ED%83%80%EB%8D%B0%EC%9D%B4%ED%84%B0) → "데이터의 대한 데이터", "어떤 목적을 가지고 만들어진 데이터", "데이터의 추가 정보"

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

## Reflect

> ES6에서 도입된 내장 객체
>
> 리플렉션은 코드가 실행되는 동안 스스로 검사하고 수정할 수 있는 기능

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

### 메타데이터 추가

> key: value 구조의 메타데이터 추가
>
> metadataKey에 식별되므로 원하는 만큼 메타데이터를 추가할 수 있다.

```javascript
Reflect.defineMetadata(metadataKey, metadataValue, target);

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

### 메타데이터 가져오기

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

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

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

### 그 외 다양한 api

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

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

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

{% hint style="info" %}
**메타 프로그래밍이란?**

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

## Decorator(@)

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

[타입스크립트 "데코레이터"의 해부학 및 사용 패턴](https://medium.com/jspoint/anatomy-of-typescript-decorators-and-their-usage-patterns-487729b34ae6)

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

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

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

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

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

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

### Reflect.metadata()

> Reflect.metadata()는 decorator(@)를 만드는 메서드
>
> 내부적으로 데코레이션하는 개체에 메타데이터를 추가하는 `Reflect.defineMetadata`를 구현한다

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

함수로 만들어서 사용&#x20;

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

@fooDecrator()
class WoongClass { }

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


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://taewoongs-organization.gitbook.io/jtwjs-dev-wiki/dev_road/week-6/reflect-metadata.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
