본문 바로가기

공부기록/Typescript

experimental decorators 사용해보기

1. 설정하기 

ts.config파일에서 

아랫부분에 있는 experimentalDecorators 를 주석 해제한다. 

앞에 콤마를 붙여 설정이 잘 되도록 한다.

 

 "experimentalDecorators": true

 

 

2. 클래스 전체에 적용되는 데코레이터 사용해보기

 

1) 초기설정

 

 

class Person {
  name = "Jenner";

  constructor() {
    console.log("Creating person object");
  }
}

const pers = new Person();

console.log(pers);

 

constructor를 만들고 실행되는지 console.log로 실행하는 코드를 입력하고 

새로운 인스턴스를 만들어준다. 

 

터미널에서 해당 파일의 경로로 이동하여

 

 

npm start

를 입력, 

또 다른 터미널을 열어 해당 파일의 경로로 이동하여

 

 

 

tsc --w

 

한뒤 

브라우저를 열고

http://localhost:3000/

으로 접속하여 console창을 확인하면

"Creating person object"와

console log에 입력한 인스턴스 pers가 

가 에러없이 잘 뜨는 것을 볼 수 있다. 

 

 

2) 데코레이터 사용해보기

 

 

 

데코레이터는 단순한 함수이다.

어떤것 예를들어 클래스에 적용하는 

 

대문자로 시작하는 함수를 윗부분에 만들어준다. 

(꼭 대문자일 필요는 없으나 보통 대문자로 시작)

 

function Logger() {
  console.log("Logging....");
}

@Logger

 

그리고 아랫부분에 @로 시작하여 함수명을 써준다. 

@는 타입스크립트가 읽거나 인식하는 특별한 식별자 심벌이다.

@다음에는 데코레이터 함수를 실행하는 것이 아니고, 함수를 포인트 한다.

 

 

그리고 Logger위에 마우스를 올려보면 

 

 

아래와 같은 안내문이 나타난다. 

"여기서 데코레이터로 사용될 인수(arguments)를 넣어줘야 한다"는 의미 

(현재는 너무 적은 인수가 있다고 안내)

 

이 안내문은 타입스크립트가 데코레이터를 쓰려고 한다는 것을 알아들었다는 의미이기도 하다.

 

인수의 갯수는 데코레이터를 어디에서 쓸지에 달렸다.

 

 

function Logger() {
  return function (constructor: Function) {
    console.log("Logging....");
    console.log(constructor);
  };
}

@Logger()
class Person {
  name = "Jenner";

  constructor() {
    console.log("Creating person object");
  }
}

현재 Person클래스에 추가했기 때문에 확인해보면 

Person 클래스의 constructor에는 

하나의 인수가 있으며 

그것을 데코레이터의 타겟(인수)로 삼게 된다. 

해당 인수의 타입은 Function이다 

 

 constructor() {
    console.log("Creating person object");
  }

 

그래서 데코레이터의 인수부분에는 아래와 같이 적는다. 

function Logger(target: Function) {
  console.log("Logging....");
}

 

 

 

 

데코레이터는 인스턴스화 되지 않고도 클래스가 정의만 돼도 실행된다.

클래스를 실체화 할 필요가 없음 

그래도 데코레이터 아웃풋을 얻을 수 있음 

자바스크립트가 클래스 정의, 컨스트럭터의 함수 정의만 찾으면

데코레이터가 실행된다.

그 컨스트럭트 함수를 인스턴스화 하기 위해 사용할때가 아니라 말이다.

 

function Logger(constructor: Function) {
  console.log("Logging....");
  console.log(constructor);
}

@Logger
class Person {
  name = "Jenner";

  constructor() {
    console.log("Creating person object");
  }
}

const pers = new Person();

console.log(pers);

 

 

3) 데코레이터 팩토리 작업하기

 

데코레이터 팩토리는

데코레이터 함수를 return 하며

어떤 대상에 데코레이터를 할당할 때

설정할 수 있도록 해준다. 

 

아까 만든 Logger함수의 인수부분을 삭제하고 

대신 컨스트럭터 인수를 받아들이는 새 익명함수를 return 한다 

 

 

이 데코레이터를 적용하려면 함수를 실행해야 한다.

바깥 함수 function Logger를 실행하기 위해.

그리고 리턴 값으로 넣은 안쪽 함수를 넣었다.

이건 클래스에 데코레이터로서 유효한 데코레이터 함수이다. 

//데코레이터 팩토리 작업하기
function Logger() {
  return function (constructor: Function) {
    console.log("Logging....");
    console.log(constructor);
  };
}

@Logger()
//여기서는 함수를 실행해야 한다.

 

 

 

왜 이렇게 하냐하면 

데코레이터 팩토리에 인수를 받을 수 있고 

그걸 logString 이라고 해본다(인수 이름과 갯수는 자유) 

타입도 지정해준다.

 

//데코레이터 팩토리 작업하기
function Logger(toString: string) {
  return function (constructor: Function) {
    console.log("Logging....");
    console.log(constructor);
  };
}

 

그리고 아랫부분 @기호와 포인터 뒤에 

타입에 맞는 인수를 넣어준다. 

 

//데코레이터 팩토리 작업하기
function Logger(logString: string) {
  return function (constructor: Function) {
    console.log("Logging....");
    console.log(constructor);
  };
}

@Logger('LOGGING - PERSON')

 

그 인수는 데코레이터 함수 안에서 사용할 수 있다. 

 

 

//데코레이터 팩토리 작업하기
function Logger(logString: string) {
  return function (constructor: Function) {
    console.log("Logging....");
    
    //추가한 로직
    console.log(logString)
    
    console.log(constructor);
  };
}

@Logger('LOGGING - PERSON')

 

 

 

팩토리 함수와 함께 실행될 때 

데코레이터 함수가 사용하는 값을 커스터마이즈(customize)할 수 있다.

 

데코레이터를 불러내는데, 

데코레이터 함수를 실행하지 않고 

데코레이터 함수와 같은 것을 반환해줄 함수를 실행한다. 

 

그러면 데코레이터 팩토리가 리턴한 안쪽 데코레이터에 

값을 우리가 전달할 수 있게 된다.