본문 바로가기
JavaScript TypeScript

[TypeScript] Decorator를 이용한 코드 변경

by Nhahan 2023. 11. 7.
class TestClass {
  test() {
    console.log('test!');  	
  }
}

위와 같은 클래스가 존재할 때, test() 메소드를 실행시키면

test!

가 터미널에 찍힐 것이다.

 

이를 test? 로 출력하기 위해 데코레이터로 코드를 바꾸어 실행 결과를 바꿀 수 있다.

 

function Test(target: any, key: string, descriptor: PropertyDescriptor) {
  const stringified = String(descriptor.value);
  const matches = stringified.match(/\{([^}]+)\}/);
  const extracted = matches[1].replace('!', '?');
  const execute = new Function(extracted);
  execute();
}

class TestClass {
  @Test
  test() {
    console.log('test!');  	
  }
}

 

@Test 라는 데코레이터를 만들고 안에서 적절하게 !를 ?로 replace 해준 뒤, test() 메소드를 실행시키면

 

test?

가 터미널에 출력된다.

 


그래서 어디에 쓸건데?

 

최근에 타입스크립트 sql mapper를 만들 일이 있었는데, 자동으로 key, value를 매핑해주는건 사실상 실패했다. 결국 하드코딩을 통해서 해결할 수 밖에 없었다.

 

그러나 만약 이러한 방법을 사용한다면 충분히 런타임에 key, value를 매핑해줄 수 있다.

 

 예를 들어,

const obj = { helloWorld: 'hi' }

라는 객체가 있고 obj.helloWorld라는 키를 DB 테이블의 HELLO_WORLD  컬럼과 매핑시켜야한다고 할 때,

 

db.execute(
  // ...,
  { key: 'HELLO_WORLD', value: obj.helloWorld },  
);

이러한 컬럼명을 하드코딩 해야한다.

이를 general 하게 적용하기 위해 key와 value 값을 자동으로 매핑시켜주려면... 이게 일반적인 방법으론 어렵다.

왜냐하면 노드는 동적으로 런타임에 타입을 추출해낼 수가 없고, 그렇기 때문에 key값을 매핑해주기 힘들다. (Go나 자바는 Reflection이라는 도구가 있는 것에 반해)

 

그러나 데코레이터를 이용하여, obj.helloWorld를 파싱해서 HELLO_WORLD를 만들어주는 식으로 구현해낼 수 있을 것으로 상상이 된다.

물론 오버헤드가 분명 존재할 것이기에 사용하기 전에 성능 측정은 필요!

댓글