데코레이터 활용편

나현·2023년 4월 12일
0
post-thumbnail

급변하는 기술 시장에서 살아남기 위해 Typescript 공부를 시작하였습니다...
과연 저는 살아남을 수 있을까요?!

👀 들어가기에 앞서...

이번에는 지난 데코레이터 기본편에 이해 데코레이터 활용편입니다!
데코레이터를 어떻게 활용하는지 예제와 함께 살펴보려 합니다.

그냥 보시는 것보다 지난번의 데코레이터 기본편과 함께 보시면 좀 더 이해에 도움이 될 것입니다 :)

👀 클래스에서 데코레이터 사용하기

앞서 클래스 및 클래스 멤버(생성자, 메서드 등등...)에 데코레이터를 사용할 수 있다고 했는데요,
클래스에서 어떻게 데코레이터를 사용할지 살펴보겠습니다.

1. 기본 사용하기

앞서 데코레이터는 함수 형태라고 했습니다.
그렇기에 데코레이터로 사용할 함수를 만들어 줍니다.
함수명은 정해진 것은 아니지만 대문자로 사용하는 경우가 많습니다.

전달인자로는 무엇을 받을까요?
클래스 데코레이터의 전달인자는 대상 클래스의 생성자 함수입니다.

function PrintInfo(constructor: Function) {
	console.log("학생의 정보를 출력합니다:");
	console.log(constructor);
}

그 다음 이 데코레이터를 사용할 클래스를 다음과 같이 만들고,
인스턴스도 하나 생성하겠습니다.

class Student {
	name = "김멍파치";

	constructor() {
		console.log(`학생의 이름은 ${this.name} 입니다.`);
	}
}

const student1 = new Student();

준비가 다 되었는데요,
만들어둔 데코레이터 PrintInfo를 Student 클래스에 연결하여 사용해볼까요?
다음과 같이 연결할 때는 '@+데코레이터명'를 클래스 위에 작성하면 합니다.

function PrintInfo(constructor: Function) {
	console.log("학생의 정보를 출력합니다:");
	console.log(constructor);
}

@PrintInfo
class Student {
	name = "김멍파치";

	constructor() {
		console.log(`학생의 이름은 ${this.name} 입니다.`);
	}
}

const student1 = new Student();

그러면 콘솔창에서

이렇게 뜨는 것을 확인할 수 있습니다!

2. 데코레이터 활용하기

데코레이터를 활용하면 클래스에서 다음과 같이 활용해 볼 수 있습니다.
예를 들면, 생성자 함수의 내용을 확장한다던지요!

//생성자 함수를 확장하는 데코레이터
function myDecorator(content:string) {
  console.log('생성자 함수를 확장합니다');
  return function(originalConstructor: any) {
    return class extends originalConstructor {
      constructor() {
        super();
        //여기에 생성자 함수를 확장합니다!
        console.log(this.userId);
      }
    };
  };
}

그러나 만약 특정 프로퍼티를 받아야 해서 이에 대한 코드를 작성하면,
아마 에러가 뜰 수도 있습니다.
만약 위 예제처럼 this.userId를 활용하는데, 이 값이 확실치 않다면?

이럴 때 제네릭을 활용해 볼 수 있습니다.
제네릭이 뭔지 가물가물하다면? 🔗제네릭 타입 포스팅 을 참고하세요!

//생성자 함수를 확장하는 데코레이터
function myDecorator(content:string) {
  console.log('생성자 함수를 확장합니다');
  //1.
  return function<T extends { new (...args: any[]): {userId: number} }>(
  originalConstructor: T
  ) {
    return class extends originalConstructor {
      //2.
      constructor(..._: any[]) {
        super();
        //여기에 생성자 함수를 확장합니다!
        console.log(this.userId);
      }
    };
  };
}

위의 코드를 좀 더 설명하도록 하겠습니다!
1. <T extends { new (...args: any[]): {userId: number} }>
예제를 제네릭 함수를 이용해 바꿔보았습니다.
userId부분을 활용해야 하기에 userId가 반드시 들어있되,
나머지는 선택적으로 들어있는 클래스를 적용한다는 의미입니다.
2. constructor(..._: any[])
원래는 ..._자리에 ...args와 같이 사용했습니다.
그런데 이 매개변수를 활용하지 않는데도 작성하면 타입스크립트에서는 에러가 납니다.
매개변수를 당장은 활용하지 않지만, 일단 받아올 수 없을까요?
이럴 때는 _를 써서 타입스크립트가 이를 허용하도록 해줄 수 있습니다!

이렇게 데코레이터를 활용하면 클래스에 여러 기능 등을 유용하게 추가하여 사용할 수 있습니다.
위 예제처럼 생성자 함수를 수정하거나, this의 bind 처리, 유효성 검사 등 자주 쓰는 여러 기능 등을 데코레이터와 함께 할용할 수 있습니다!


😝 마무리

길고 긴 데코레이터에 대해 알아보는 시간이었습니다...
이번에는 내용이 많아서 하마터면 살아남지 못할 뻔 했으나!
간신히 살아남았네요.

저는 다음 시간에도 살아남을 수 있을까요?!😂

profile
프론트엔드 개발자 NH입니다. 시리즈로 보시면 더 쉽게 여러 글들을 볼 수 있습니다!

0개의 댓글