Web Development

[콜럼Vue스] Proxy

쟤리 2024. 10. 1. 22:49
728x90
반응형

**Proxy**는 **ES6(ECMAScript 6)**에서 도입된 기능으로, **객체의 기본 동작(프로퍼티 접근, 값 할당, 함수 호출 등)**을 가로채서 제어하거나 수정할 수 있게 해주는 강력한 도구임. Proxy를 사용하면 객체에 대한 커스텀 동작을 정의할 수 있으며, 특정 상황에 맞는 동작을 추가하거나 객체의 기본적인 동작 방식을 바꿀 수 있음.

 

1. Proxy의 기본 개념

Proxy는 두 개의 인자를 받음:

  • 타겟 객체(target): 감시하거나 가로채고 싶은 원래 객체.
  • 핸들러(handler): 객체의 동작을 가로채고 **수정할 트랩(traps)**을 정의한 객체. 다양한 트랩을 통해 원하는 동작을 추가하거나 수정할 수 있음.
const target = {
  message: "Hello, Proxy!"
};

const handler = {
  get: (target, property) => {
    return property in target ? target[property] : "Property not found!";
  }
};

const proxy = new Proxy(target, handler);

console.log(proxy.message); // "Hello, Proxy!"
console.log(proxy.nonexistent); // "Property not found!"

 

  • target: Proxy가 감시할 대상 객체.
  • handler: get 트랩을 사용하여 프로퍼티 접근을 가로채고, 존재하지 않는 프로퍼티에 대한 커스텀 동작을 정의함.
  • proxy: 타겟 객체의 동작을 제어하는 프록시 객체.

2. Proxy 핸들러의 트랩

**핸들러(handler)**에는 여러 **트랩(trap)**이 정의될 수 있으며, Proxy 객체는 다양한 객체 동작을 가로채서 처리할 수 있음. 다음은 자주 사용되는 몇 가지 트랩임.

(1) get 트랩

  • 객체의 프로퍼티에 접근할 때 동작을 가로챔.
const handler = {
  get: (target, property) => {
    return property in target ? target[property] : "Property not found!";
  }
};

const proxy = new Proxy({ name: "Jerry" }, handler);
console.log(proxy.name); // "Jerry"
console.log(proxy.age);  // "Property not found!"

 

  • get 트랩은 객체의 프로퍼티를 접근할 때 특정 로직을 적용할 수 있게 해줌.

(2) set 트랩

  • 객체의 프로퍼티에 값을 할당할 때 동작을 가로챔.
const handler = {
  set: (target, property, value) => {
    if (typeof value === "number") {
      target[property] = value;  // 값이 숫자일 때만 할당 허용
      return true;
    } else {
      console.log("Invalid value type, only numbers are allowed.");
      return false;
    }
  }
};

const proxy = new Proxy({}, handler);
proxy.age = 30;   // 정상 작동
proxy.age = "thirty";  // "Invalid value type, only numbers are allowed."
  • set 트랩은 값의 타입을 검사하거나, 값 할당을 제어할 때 유용하게 사용할 수 있음.

(3) has 트랩

  • in 연산자를 사용할 때 동작을 가로챔.
const handler = {
  has: (target, property) => {
    if (property === "secret") {
      return false; // "secret" 프로퍼티는 항상 숨김
    }
    return property in target;
  }
};

const proxy = new Proxy({ message: "Hello" }, handler);
console.log("message" in proxy); // true
console.log("secret" in proxy);  // false
  • has 트랩은 객체에서 특정 프로퍼티를 숨기거나 커스텀 조건을 추가할 때 유용함.

 

(4) deleteProperty 트랩

  • delete 연산자를 사용할 때 동작을 가로챔.
const handler = {
  deleteProperty: (target, property) => {
    if (property in target) {
      delete target[property];
      console.log(`${property} has been deleted.`);
      return true;
    }
    return false;
  }
};

const proxy = new Proxy({ name: "Jerry" }, handler);
delete proxy.name; // "name has been deleted."
  • deleteProperty 트랩은 프로퍼티가 삭제될 때 동작을 가로채 커스텀 동작을 정의할 수 있음.

 

 

3. Proxy 활용 예시

(1) 데이터 유효성 검사

Proxy를 이용해 객체의 값을 할당할 때 유효성 검사를 수행할 수 있음.

const validator = {
  set: function(target, property, value) {
    if (property === "age" && typeof value !== "number") {
      throw new TypeError("Age must be a number.");
    }
    target[property] = value;
    return true;
  }
};

const person = new Proxy({}, validator);
person.age = 25;   // 정상 동작
person.age = "twenty-five";  // 오류 발생: "Age must be a number."
  • set 트랩을 통해 객체의 프로퍼티에 값을 할당할 때, 유효성 검사를 수행하고 잘못된 값에 대해 오류를 발생시킬 수 있음.

(2) 자동 계산 필드

프록시를 사용하면 객체의 프로퍼티에 접근할 때 자동으로 계산된 값을 제공할 수 있음.

const product = {
  price: 100,
  quantity: 2
};

const handler = {
  get: function(target, property) {
    if (property === "total") {
      return target.price * target.quantity;  // price * quantity 계산 후 반환
    }
    return target[property];
  }
};

const proxy = new Proxy(product, handler);
console.log(proxy.total); // 200
  • get 트랩을 사용하여 total 프로퍼티에 접근할 때 자동으로 계산된 값을 반환할 수 있음.

(3) 로깅 및 디버깅

Proxy를 사용해 객체의 모든 동작을 감시하고, 값이 변경되거나 접근될 때 로그를 남길 수 있음

const person = {
  name: "Jerry",
  age: 25
};

const handler = {
  get: function(target, property) {
    console.log(`Getting property ${property}`);
    return target[property];
  },
  set: function(target, property, value) {
    console.log(`Setting property ${property} to ${value}`);
    target[property] = value;
    return true;
  }
};

const proxy = new Proxy(person, handler);
proxy.name; // "Getting property name"
proxy.age = 30; // "Setting property age to 30"
  • 이 예시는 객체의 모든 프로퍼티 접근 및 수정에 대해 로그를 출력하여, 디버깅에 도움을 줄 수 있음.

4. Proxy와 Reflect

Reflect 객체는 Proxy와 함께 자주 사용되며, 객체의 기본 동작을 안전하게 수행할 수 있는 메서드를 제공함. Proxy로 기본 동작을 가로채더라도, 원래의 객체 동작을 그대로 수행하고 싶을 때 **Reflect**를 사용함.

const handler = {
  set: function(target, property, value) {
    console.log(`Setting ${property} to ${value}`);
    return Reflect.set(target, property, value);  // 기본 동작 수행
  }
};

const proxy = new Proxy({}, handler);
proxy.name = "Jerry"; // "Setting name to Jerry"

**Reflect.set**은 Proxy 내에서 기본적인 값 할당 동작을 그대로 수행하면서, 커스텀 로직도 추가할 수 있게 해줌.

 

5. Proxy의 사용 시기

Proxy는 다음과 같은 상황에서 매우 유용함:

  • 데이터 유효성 검사: 객체에 값을 할당할 때 유효성 검사를 수행할 수 있음.
  • 자동 값 계산: 특정 프로퍼티에 접근할 때 자동으로 계산된 값을 제공할 수 있음.
  • 로깅 및 디버깅: 객체의 동작을 감시하고, 로그를 남겨 디버깅할 수 있음.
  • 동적 API 생성: 객체의 프로퍼티가 동적으로 생성되거나 변경될 때 커스텀 동작을 추가할 수 있음.

요약:

  • Proxy는 객체의 동작을 가로채서 커스텀 동작을 정의할 수 있는 강력한 도구임.
  • **트랩(trap)**을 통해 프로퍼티 접근, 값 할당, 삭제, 함수 호출 등을 제어할 수 있음.
  • Reflect와 함께 사용하면 객체의 기본 동작을 안전하게 수행하면서도 커스텀 동작을 추가할 수 있음.
  • 유효성 검사, 로깅, 자동 값 계산 등 다양한 용도로 활용 가능.
728x90
반응형

'Web Development' 카테고리의 다른 글

[콜럼Vue스] Vue인스턴스  (0) 2024.10.04
[콜럼Vue스] Dynamic Arguments  (2) 2024.10.03
[콜럼Vue스] 전개연산자  (1) 2024.10.01
[콜럼Vue스] promise  (1) 2024.10.01
[콜럼Vue스] 리터럴 Literal  (1) 2024.09.30