JavaScript Proxy Reflect


자바스크립트의 ProxyReflect는 객체의 동작을 가로채고 제어하는 강력한 도구입니다. 이 두 기능을 함께 사용하면 객체의 기본 동작을 커스터마이즈하고, 필요한 경우 원래의 동작을 유지할 수 있습니다.

Proxy

Proxy 객체는 다른 객체의 기본 동작(속성 접근, 할당, 순회, 함수 호출 등)을 가로채고 재정의할 수 있도록 합니다. 이를 통해 객체의 동작을 제어하고 수정할 수 있습니다.

Proxy 생성

Proxy는 두 개의 매개변수를 받습니다:

  1. target: 프록시할 기본 객체
  2. handler: 기본 동작을 가로채기 위해 정의된 트랩(traps)들의 집합
const proxy = new Proxy(target, handler);

예제

let target = { message: "Hello, world!" };

let handler = {
    get: function(target, property) {
        if (property === 'message') {
            return target[property].toUpperCase();
        }
        return target[property];
    }
};

let proxy = new Proxy(target, handler);

console.log(proxy.message); // "HELLO, WORLD!"

주요 트랩

  • get: 속성 접근을 가로챕니다.
  get(target, property, receiver) {
      // target: 원본 객체
      // property: 접근하려는 속성
      // receiver: 프록시 또는 상속 객체
  }
  • set: 속성 할당을 가로챕니다.
  set(target, property, value, receiver) {
      // target: 원본 객체
      // property: 설정하려는 속성
      // value: 설정하려는 값
      // receiver: 프록시 또는 상속 객체
  }
  • has: in 연산자를 가로챕니다.
  has(target, property) {
      // target: 원본 객체
      // property: 검사하려는 속성
  }
  • deleteProperty: delete 연산자를 가로챕니다.
  deleteProperty(target, property) {
      // target: 원본 객체
      // property: 삭제하려는 속성
  }
  • apply: 함수 호출을 가로챕니다.
  apply(target, thisArg, argumentsList) {
      // target: 원본 함수 객체
      // thisArg: 호출 시 this 값
      // argumentsList: 호출 시 전달된 인수 목록
  }
  • construct: new 연산자를 가로챕니다.
  construct(target, argumentsList, newTarget) {
      // target: 원본 생성자 함수
      // argumentsList: 생성자 함수에 전달된 인수 목록
      // newTarget: 새로운 인스턴스의 prototype 객체
  }

Reflect

Reflect 객체는 자바스크립트의 메타프로그래밍 API를 단순화하고 일관성 있게 제공하는 표준 빌트인 객체입니다. Reflect는 객체의 기본 동작을 수행하는 정적 메서드들을 제공합니다. Reflect의 메서드는 Proxy 트랩과 동일한 이름을 가지고 있으며, 동일한 작업을 수행합니다.

Reflect의 주요 메서드

  • Reflect.get: 속성 접근
  Reflect.get(target, property, receiver);
  • Reflect.set: 속성 할당
  Reflect.set(target, property, value, receiver);
  • Reflect.has: 속성 존재 여부 확인
  Reflect.has(target, property);
  • Reflect.deleteProperty: 속성 삭제
  Reflect.deleteProperty(target, property);
  • Reflect.apply: 함수 호출
  Reflect.apply(target, thisArg, argumentsList);
  • Reflect.construct: 생성자 호출
  Reflect.construct(target, argumentsList, newTarget);

예제

ProxyReflect를 함께 사용하는 예제입니다.

let target = { message1: "hello", message2: "everyone" };

let handler = {
    get: function(target, property) {
        console.log(`Property '${property}' has been accessed`);
        return Reflect.get(target, property);
    },
    set: function(target, property, value) {
        console.log(`Property '${property}' has been set to '${value}'`);
        return Reflect.set(target, property, value);
    }
};

let proxy = new Proxy(target, handler);

console.log(proxy.message1); // "hello"
// 콘솔: Property 'message1' has been accessed

proxy.message2 = "world";
// 콘솔: Property 'message2' has been set to 'world'

console.log(proxy.message2); // "world"
// 콘솔: Property 'message2' has been accessed

실용적인 사용 사례

데이터 검증

Proxy를 사용하여 객체에 할당되는 데이터의 유효성을 검사할 수 있습니다.

let person = { name: "", age: 0 };

let handler = {
    set: function(target, property, value) {
        if (property === "age") {
            if (typeof value !== "number" || value <= 0) {
                throw new TypeError("Age must be a positive number");
            }
        }
        return Reflect.set(target, property, value);
    }
};

let proxyPerson = new Proxy(person, handler);

proxyPerson.age = 25; // 정상
console.log(proxyPerson.age); // 25

try {
    proxyPerson.age = -5; // 오류 발생
} catch (e) {
    console.error(e.message); // "Age must be a positive number"
}

속성 접근 로깅

Proxy를 사용하여 객체의 속성 접근을 로깅할 수 있습니다.

let user = { name: "Alice", email: "alice@example.com" };

let handler = {
    get: function(target, property) {
        console.log(`Accessing property '${property}'`);
        return Reflect.get(target, property);
    }
};

let proxyUser = new Proxy(user, handler);

console.log(proxyUser.name); // "Alice"
// 콘솔: Accessing property 'name'

console.log(proxyUser.email); // "alice@example.com"
// 콘솔: Accessing property 'email'

요약

ProxyReflect는 객체의 동작을 가로채고 제어하는 강력한 도구입니다. Proxy를 사용하여 객체의 기본 동작을 재정의하고, Reflect를 사용하여 원본 객체의 기본 동작을 호출할 수 있습니다. 이를 통해 객체의 동작을 맞춤 설정하거나 새로운 기능을 추가하는 등 다양한 활용이 가능합니다.


Leave a Reply

Your email address will not be published. Required fields are marked *