Proxy Pattern

Seungyeop Yeom·2022년 5월 30일
0

Design Patterns

목록 보기
2/2

대상 객체에 대한 상호 작용 가로채기 및 제어

Proxy 객체를 사용하면 특정 객체와의 상호 작용을 더 잘 제어할 수 있습니다.
Proxy 객체는 객체와 상호 작용할 때마다 동작을 결정할 수 있습니다. 예를 들어 값을 가져오거나 값을 설정할 때입니다.

일반적으로 Proxy는 다른 사람의 대역을 의미합니다. 그 사람에게 직접 말하는 대신, 당신이 연락하려고 했던 사람을 대리할 대리인과 이야기하게 될 것입니다. JavaScript에서도 동일한 일이 발생합니다. 대상 객체와 직접 상호 작용하는 대신 Proxy 객체와 상호 작용합니다.

John Doe를 나타내는 person 개체를 만들어 보겠습니다.

const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

이 객체와 직접 상호 작용하는 대신 Proxy 객체와 상호 작용하기를 원합니다. JavaScript에서는 Proxy의 새 인스턴스를 만들어 새 proxy를 쉽게 만들 수 있습니다.

const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

const personProxy = new Proxy(person, {});

Proxy의 두 번째 인수는 handler를 나타내는 객체입니다. handler 객체에서 상호 작용 유형에 따라 특정 동작을 정의할 수 있습니다.

Proxy handler에 추가할 수 있는 많은 방법이 있지만 가장 일반적인 두 가지 방법은 getset입니다.

  • get: 속성에 액세스하려고 할 때 호출됩니다.
  • set: 속성을 수정하려고 할 때 호출됩니다.

효과적으로, 일어날 일은 다음과 같습니다:

person 객체와 직접 상호 작용하는 대신 personProxy와 상호 작용합니다.

personProxy에 handler를 추가해 보겠습니다. 속성을 수정하려고 Proxy에서 set 메서드를 호출할 때 Proxy가 속성의 이전 값과 새 값을 기록하기를 원합니다. 속성에 액세스하려고 할 때 Proxy에서 get 메서드를 호출하면 Proxy가 속성의 키와 값을 포함하는 더 읽기 쉬운 문장을 log로 나타내길 원합니다.

const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    console.log(`The value of ${prop} is ${obj[prop]}`);
  },
  set: (obj, prop, value) => {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    obj[prop] = value;
  }
});

좋습니다! 속성을 수정하거나 검색하려고 할 때 어떤 일이 발생하는지 봅시다.

// index.js
const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    console.log(`The value of ${prop} is ${obj[prop]}`);
  },
  set: (obj, prop, value) => {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    obj[prop] = value;
    return true;
  }
});

personProxy.name;
personProxy.age = 43;

name 속성에 액세스할 때 Proxy는 더 보기 편한 문장을 반환했습니다. name 값은 John Doe입니다.

age 속성을 수정할 때 Proxy는 이 속성의 이전 값과 새 값을 반환했습니다. 나이가 42에서 43으로 변경되었습니다.

Proxy는 유효성 검사를 추가하는 데 유용할 수 있습니다. 사용자는 사람의 나이를 문자열 값으로 변경하거나 빈 이름을 지정할 수 없어야 합니다. 또는 사용자가 존재하지 않는 객체의 속성에 액세스하려는 경우 사용자에게 알려야 합니다.

const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    if (!obj[prop]) {
      console.log(
        `Hmm.. this property doesn't seem to exist on the target object`
      );
    } else {
      console.log(`The value of ${prop} is ${obj[prop]}`);
    }
  },
  set: (obj, prop, value) => {
    if (prop === "age" && typeof value !== "number") {
      console.log(`Sorry, you can only pass numeric values for age.`);
    } else if (prop === "name" && value.length < 2) {
      console.log(`You need to provide a valid name.`);
    } else {
      console.log(`Changed ${prop} from ${obj[prop]} to ${value}.`);
      obj[prop] = value;
    }
  }
});

잘못된 값을 전달하려고 할 때 어떤 일이 발생하는지 봅시다!

// index.js
const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    if (!obj[prop]) {
      console.log(`Hmm.. this property doesn't seem to exist`);
    } else {
      console.log(`The value of ${prop} is ${obj[prop]}`);
    }
  },
  set: (obj, prop, value) => {
    if (prop === "age" && typeof value !== "number") {
      console.log(`Sorry, you can only pass numeric values for age.`);
    } else if (prop === "name" && value.length < 2) {
      console.log(`You need to provide a valid name.`);
    } else {
      console.log(`Changed ${prop} from ${obj[prop]} to ${value}.`);
      obj[prop] = value;
    }
    return true;
  }
});

personProxy.nonExistentProperty;
personProxy.age = "44";
personProxy.name = "";

프록시는 잘못된 값으로 person 개체를 수정하지 않았는지 확인하여 데이터를 순수하게 유지하는데 도움이 됩니다!

Reflect

javaScript는 Reflect 라는 내장 객체를 제공하므로 프록시로 작업할 때 대상 객체를 더 쉽게 조작할 수 있습니다.

이전에는 대괄호 표기법으로 값을 직접 가져오거나 설정하여 프록시 내에서 대상 개체의 속성을 수정하고 액세스하려고 했습니다. 대신 Reflect 객체를 사용할 수 있습니다. Reflect 객체의 메서드는 handler 객체의 메서드와 이름이 같습니다.

obj[prop]를 통해 속성에 액세스하거나 obj[prop] = value를 통해 속성을 설정하는 대신 Reflect.get()Reflect.set()을 통해 대상 객체의 속성에 액세스하거나 수정할 수 있습니다.

const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    console.log(`The value of ${prop} is ${Reflect.get(obj, prop)}`);
  },
  set: (obj, prop, value) => {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    Reflect.set(obj, prop, value);
  }
});

Reflect 개체를 사용하여 대상 개체의 속성에 쉽게 액세스하고 수정할 수 있습니다.

// index.js
const person = {
  name: "John Doe",
  age: 42,
  nationality: "American"
};

const personProxy = new Proxy(person, {
  get: (obj, prop) => {
    console.log(`The value of ${prop} is ${Reflect.get(obj, prop)}`);
  },
  set: (obj, prop, value) => {
    console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
    return Reflect.set(obj, prop, value);
  }
});

personProxy.name;
personProxy.age = 43;
personProxy.name = "Jane Doe";

프록시는 개체의 동작에 대한 제어를 추가하는 강력한 방법입니다. 프록시는 다양한 사용 사례를 가질 수 있습니다. 유효성 검사, 형식 지정, 알림 또는 디버깅에 도움이 될 수 있습니다.

Proxy 개체를 과도하게 사용하거나 각 처리기 메서드 호출에 대해 과중한 작업을 수행하면 응용 프로그램 성능에 쉽게 부정적인 영향을 줄 수 있습니다. 성능이 중요한 코드에는 프록시를 사용하지 않는 것이 가장 좋습니다.

profile
좋은 개발 정보를 함께 공유하고 싶습니다. 피드백은 언제나 환영합니다!

0개의 댓글