ES6(ECMAScript 2015) – 프록시와 리플렉션 – 0 – 프록시(Proxy) 객체

ES6(ECMAScript 2015) - 객체 리터럴 확장 - 2 - 프로토타입 축약
ES6(ECMAScript 2015) – 프록시와 리플렉션 – 0 – 프록시(Proxy) 객체

ES6(ECMAScript 2015) – 프록시와 리플렉션 – 0 – 프록시(Proxy) 객체

프록시(Proxy) 객체란 무엇인가요?

프록시(Proxy) 객체는 ES6(ECMAScript 2015)에서 도입된 기능으로, 다른 객체의 동작을 가로채고 커스텀 로직을 적용할 수 있게 해줍니다. 프록시는 객체 사이에서 중개자 역할을 하며, 객체에 접근하는 것을 가로채어 특정 동작을 수행하거나 제어할 수 있습니다.

프록시 객체는 대상 객체를 감싸는 래퍼(wrapper) 역할을 합니다. 이 래퍼는 대상 객체에 접근하는 모든 요청을 가로채고 필요한 경우 수정하거나 대체할 수 있습니다. 이렇게 프록시를 통해 객체에 대한 접근을 제어할 수 있기 때문에 객체의 동작을 동적으로 수정하거나 모니터링할 수 있습니다.

프록시(Proxy) 객체의 예시

예를 들어, 프록시를 사용하여 객체의 속성에 접근할 때 특정 로그를 남기는 기능을 추가해보겠습니다.

const targetObject = {
  name: 'John',
  age: 30
};

const handler = {
  get(target, property, receiver) {
    console.log(`속성에 접근 중: ${property}`);
    return Reflect.get(target, property, receiver);
  }
};

const proxyObject = new Proxy(targetObject, handler);

console.log(proxyObject.name);
console.log(proxyObject.age);

위의 코드에서 targetObject는 원본 객체이고, handler는 프록시 객체의 동작을 정의한 핸들러입니다. handlerget 메서드를 가지고 있어 프록시 객체의 속성에 접근할 때마다 해당 속성 이름을 로그에 출력하도록 설정하였습니다.

new Proxy(targetObject, handler)를 통해 proxyObject를 생성하고, proxyObject의 속성에 접근하면 핸들러의 get 메서드가 실행되며 로그가 출력됩니다. 이를 통해 프록시를 사용하여 객체의 속성에 접근하고 원하는 로직을 수행할 수 있습니다.

프록시는 다양한 동작을 가로챌 수 있으며, 접근자(getter), 설정자(setter), 함수 호출, 속성 삭제 등을 가로챌 수 있습니다. 자세한 내용은 핸들러 객체의 다양한 메서드를 활용하여 제어할 수 있습니다.

프록시(Proxy) 객체의 활용 예시

프록시 객체는 객체의 동작을 변경하거나 가로챌 수 있는 강력한 기능을 제공합니다. 이를 활용하여 다양한 상황에서 유용하게 사용할 수 있습니다.

1. 속성 값의 유효성 검사

프록시를 사용하여 객체의 속성 값에 유효성 검사를 적용할 수 있습니다. 예를 들어, 특정 속성에 문자열만 할당하고자 할 때 프록시를 활용할 수 있습니다.

const user = {
  name: '',
  age: 25
};

const handler = {
  set(target, property, value, receiver) {
    if (property === 'name' && typeof value !== 'string') {
      throw new Error('이름은 문자열이어야 합니다.');
    }
    return Reflect.set(target, property, value, receiver);
  }
};

const proxyUser = new Proxy(user, handler);

proxyUser.name = 'John';  // 유효한 값, 문제 없음
console.log(proxyUser.name);  // "John"

proxyUser.name = 123;  // 유효하지 않은 값, 에러 발생
console.log(proxyUser.name);  // 이 줄은 실행되지 않음

위의 코드에서 handlerset 메서드를 사용하여 name 속성에 할당되는 값이 문자열인지 확인하고, 그렇지 않을 경우 에러를 발생시킵니다. 이렇게 프록시를 활용하면 객체의 속성 값에 제약을 두거나 특정 규칙을 적용할 수 있습니다.

2. 캐싱 기능 추가

프록시를 사용하여 함수의 결과를 캐싱하는 기능을 추가할 수 있습니다. 함수의 결과를 한 번 계산한 후, 같은 인자에 대해 다시 호출될 때는 캐싱된 결과를 반환하도록 프록시를 설정할 수 있습니다.

function expensiveOperation(n) {
  console.log('계산 중...');
  // 복잡한 계산 로직
  return n * 2;
}

const cache = {};

const handler = {
  apply(target, thisArg, args) {
    const argKey = JSON.stringify(args);
    if (argKey in cache) {
      console.log('캐시된 결과 반환');
      return cache[argKey];
    }
    const result = Reflect.apply(target, thisArg, args);
    cache[argKey] = result;
    return result;
  }
};

const proxyExpensiveOperation = new Proxy(expensiveOperation, handler);

console.log(proxyExpensiveOperation(5));  // 캐시되지 않음, 계산 중...
console.log(proxyExpensiveOperation(5));  // 캐시된 결과 반환

위의 코드에서 handlerapply 메서드를 사용하여 함수 호출을 가로채고, 함수의 인자를 기반으로 캐시된 결과를 확인하고 반환하도록 설정했습니다. 이를 통해 계산 비용이 많이 드는 연산의 결과를 한 번 계산한 후, 이후 호출에서는 캐시된 결과를 사용할 수 있습니다.

프록시를 사용하여 객체의 동작을 가로채고 제어하는 방법은 다양합니다. 위에서 소개한 예시 이외에도 프록시를 활용하여 로깅, 성능 측정, 접근 제어 등 다양한 기능을 구현할 수 있습니다.

프록시(Proxy) 객체 사용 시 주의해야 할 점

프록시 객체를 사용할 때 몇 가지 주의할 점이 있습니다.

  1. 프록시 객체는 원본 객체를 감싸는 래퍼로써, 원본 객체와 동일한 인터페이스를 제공해야 합니다. 즉, 프록시 객체는 원본 객체와 같은 속성과 메서드를 가지고 있어야 합니다.

  2. 프록시 객체의 핸들러 메서드는 프록시 객체 자신의 속성으로 정의되지 않아야 합니다. 그렇지 않으면 핸들러 메서드 내에서 this를 사용할 때 예기치 않은 동작이 발생할 수 있습니다.

  3. 프록시 객체를 사용하는 도중 예외가 발생하면, 예외가 핸들러로 전파되어야 합니다. 예외를 무시하거나 처리하지 않으면 예외의 원인을 파악하기 어려울 수 있습니다.

  4. 프록시 객체는 대상 객체의 동작을 가로채기 때문에 성능에 영향을 줄 수 있습니다. 따라서 프록시 객체를 사용할 때 성능에 주의해야 합니다. 불필요한 추가 작업이 없도록 신중하게 구현해야 합니다.

프록시 객체를 사용하면 객체의 동작을 가로채고 커스텀 로직을 적용할 수 있습니다. 이를 통해 유효성 검사, 캐싱, 로깅 등 다양한 기능을 추가하거나 객체에 대한 접근을 제어할 수 있습니다. 프록시는 ES6에서 도입된 강력한 기능이며, 자바스크립트 개발에서 유용하게 활용될 수 있습니다.

답글 남기기