Typescript:데코레이터

hwisaac·2023년 2월 25일
0

데코레이터(Decorator)는 클래스, 프로퍼티, 메서드, 파라미터에 부가적인 정보를 추가하거나 수정하는 문법입니다.

데코레이터는 @ 기호를 이용해서 표현하며, 함수와 클래스를 인자로 받습니다. 데코레이터를 이용해서 클래스에 추가적인 정보를 부여하거나 기능을 확장할 수 있습니다.

데코레이터의 유형

TypeScript에서 데코레이터는 다음과 같은 몇 가지 유형이 있습니다.

  • 클래스 데코레이터(Class Decorator): 클래스 선언에 사용되며, 생성자 함수를 인수로 받습니다. 클래스 선언이 생성될 때 호출되어 클래스를 수정하거나 다른 생성자 함수로 변경하는 등의 작업을 수행할 수 있습니다.
  • 메서드 데코레이터(Method Decorator): 메서드 선언에 사용되며, 세 개의 인수를 받습니다. 첫 번째 인수는 데코레이터가 적용된 메서드의 프로토타입 객체입니다. 두 번째 인수는 메서드의 이름입니다. 세 번째 인수는 메서드 디스크립터입니다.
  • 프로퍼티 데코레이터(Property Decorator): 프로퍼티 선언에 사용되며, 두 개의 인수를 받습니다. 첫 번째 인수는 데코레이터가 적용된 프로퍼티의 프로토타입 객체입니다. 두 번째 인수는 프로퍼티의 이름입니다.
  • 매개변수 데코레이터(Parameter Decorator): 메서드 또는 생성자의 매개변수에 사용되며, 세 개의 인수를 받습니다. 첫 번째 인수는 데코레이터가 적용된 메서드 또는 생성자의 프로토타입 객체입니다. 두 번째 인수는 데코레이터가 적용된 매개변수의 이름입니다. 세 번째 인수는 매개변수의 인덱스입니다.

데코레이터의 목적

데코레이터는 주로 클래스, 메서드, 프로퍼티에 추가적인 동작을 부여할 때 사용됩니다.

예를 들어, 클래스에 데코레이터를 사용하면 클래스의 생성자를 수정하거나 클래스 자체에 어떤 동작을 부여할 수 있습니다.

데코레이터를 메서드나 프로퍼티에 사용하면 해당 메서드나 프로퍼티에 대한 추가적인 정보를 제공하거나 동작을 변경할 수 있습니다.

데코레이터는 주로 코드의 재사용성을 높이거나, 코드를 더욱 깔끔하게 유지하기 위해 사용됩니다.

또한, 데코레이터는 코드를 더욱 가독성 있게 만들어주며, 특히 큰 규모의 프로젝트에서 유지보수성을 높이는 데 큰 역할을 합니다.

TypeScript에서는 데코레이터가 코드 구조에 "장식"을 하는 역할을 하기 때문에, 이를 강조하기 위해 "Decorator"라는 용어를 사용하게 되었습니다.

데코레이터가 코드 구조에 미치는 영향은 코드 실행과 직접적인 연관이 없으며, 간단히 말해서 코드의 기능과는 관련이 없는 부가적인 정보를 추가하는 역할을 합니다.

이러한 역할을 함으로써, 데코레이터는 TypeScript에서 코드의 가독성을 높이고 유지보수성을 향상시키는데 도움을 줄 수 있습니다

데코레이터의 적용 예시

Copy code
// 데코레이터 적용 전 클래스
class User {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

// 데코레이터 적용 후 클래스
@logger
class User {
  name: string;
  age: number;
  constructor(name: string, age: number) {
    this.name = name;
    this.age = age;
  }
}

function logger<T extends { new(...args: any[]): {} }>(constructor: T) {
  return class extends constructor {
    constructor(...args: any[]) {
      super(...args);
      console.log(`Created an instance of ${constructor.name}`);
    }
  }
}

위의 예시에서, User 클래스에 @logger 데코레이터를 적용했습니다. 이 데코레이터는 클래스가 인스턴스화될 때 해당 클래스의 이름을 출력하도록 하는 간단한 로깅 기능을 추가합니다.

데코레이터를 적용하기 전에는, User 클래스가 인스턴스화될 때 로깅 기능이 없기 때문에 다음과 같이 코드를 작성해야 합니다.

Copy code
const user = new User('John', 30);
console.log(user); // User { name: 'John', age: 30 }

하지만 데코레이터를 적용하면, 클래스가 인스턴스화될 때 로깅 기능이 실행되므로 다음과 같이 출력됩니다.

Copy code
const user = new User('John', 30);
// Created an instance of User
console.log(user); // User { name: 'John', age: 30 }

즉, 데코레이터를 적용함으로써 User 클래스의 인스턴스 생성 시 로깅 기능이 부가되었습니다. 이처럼 데코레이터를 사용하면, 기존의 코드를 수정하지 않고도 부가적인 기능을 추가할 수 있습니다.

더많은 예시

클래스 데코레이터

function classDecorator<T extends {new(...args:any[]):{}}>(constructor:T) {
  return class extends constructor {
      newProperty = "new property";
      hello = "override";
  }
}

@classDecorator
class MyClass {
  property = "property";
  hello: string;
  constructor(m: string) {
      this.hello = m;
  }
}

console.log(new MyClass("world").newProperty); // "new property"

위 코드에서 @classDecorator가 MyClass 클래스 위에 붙어있는데, 이는 MyClass 클래스에 대해 classDecorator 라는 함수를 적용하겠다는 뜻입니다. classDecorator는 새로운 클래스를 반환하는데, 이 클래스는 MyClass의 서브클래스로서 newProperty라는 새로운 프로퍼티를 추가하고 hello 프로퍼티를 오버라이드합니다. 따라서 new MyClass("world").newProperty를 출력하면 "new property"가 나옵니다.

메서드 데코레이터

function methodDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  console.log(`methodDecorator called on ${propertyKey}`);
}

class MyClass {
  @methodDecorator
  myMethod() {}
}

위 코드에서 @methodDecoratormyMethod 메서드 위에 붙어있는데, 이는 MyClass 클래스의 myMethod 메서드에 대해 methodDecorator 함수를 적용하겠다는 뜻입니다. methodDecorator 함수는 세 개의 인자를 받는데, 첫 번째는 타겟 객체, 두 번째는 프로퍼티 키, 세 번째는 프로퍼티 디스크립터입니다. 위 코드에서는 console.log를 이용해서 메서드 데코레이터가 실행됐음을 확인할 수 있습니다.

프로퍼티 데코레이터

function propertyDecorator(target: any, propertyKey: string) {
  console.log(`propertyDecorator called on ${propertyKey}`);
}

class MyClass {
  @propertyDecorator
  myProperty: string;
}

위의 코드는 MyClass 클래스의 myProperty 프로퍼티에 프로퍼티 데코레이터를 적용한 예시입니다. 프로퍼티 데코레이터 함수인 propertyDecorator는 두 개의 인자를 받습니다. 첫 번째 인자는 데코레이터가 적용되는 클래스의 인스턴스를 가리키는 객체이고, 두 번째 인자는 데코레이터가 적용되는 프로퍼티의 이름을 가리킵니다.

프로퍼티 데코레이터는 주로 클래스의 프로퍼티에 메타데이터를 추가하기 위해 사용됩니다. 위의 예시에서는 console.log를 이용하여 myProperty 프로퍼티에 데코레이터가 적용됐음을 출력하고 있습니다. 따라서, 이를 통해 런타임 시점에 프로퍼티에 대한 추가 정보를 제공할 수 있습니다.

매개변수 데코레이터

매개변수 데코레이터는 함수나 메서드의 매개변수에 데코레이터를 적용할 수 있는 기능입니다. 매개변수 데코레이터를 사용하면 함수나 메서드의 매개변수에 부가적인 정보를 추가할 수 있습니다.

매개변수 데코레이터는 다음과 같은 형식을 가집니다.

function parameterDecorator(target: Object, propertyKey: string | symbol, parameterIndex: number) {
  // ...
}
  • target: 데코레이터가 적용될 클래스의 프로토타입 객체입니다.
  • propertyKey: 데코레이터가 적용될 메서드의 이름이나 생성자 함수입니다.
  • parameterIndex: 데코레이터가 적용될 매개변수의 인덱스입니다.

다음은 매개변수 데코레이터를 사용한 예시입니다.

function logParameter(target: any, methodName: string, parameterIndex: number) {
  console.log(`LogParameter: ${target}, ${methodName}, ${parameterIndex}`);
}

class MyClass {
  greet(@logParameter message: string) {
    console.log(message);
  }
}

const myClass = new MyClass();
myClass.greet("Hello, World!");

위의 예시에서 logParameter 데코레이터가 greet 메서드의 첫 번째 매개변수 message에 적용됩니다. logParameter 함수는 데코레이터가 적용된 매개변수의 정보를 출력합니다. MyClass 클래스를 인스턴스화하고 greet 메서드를 호출할 때 데코레이터가 실행되며, 메시지와 함께 "Hello, World!"가 출력됩니다. 출력 결과는 다음과 같습니다.

LogParameter: [object Object], greet, 0
Hello, World!

매개변수 데코레이터를 사용하면 예를 들어, 유효성 검사, 로깅 등과 같은 부가적인 작업을 수행할 수 있습니다.

0개의 댓글