woolta

자바스크립트 Proxy 에 대하여 알아보자.!!

wooltaUserImgb00032 | javaScript | 2019-07-06

프록시 (Proxy)

프록시 는 객체의 속성 접근, 속성 할당, 순회, 함수 호출 등 객체의 기본적인 동작의 새로운 행동을 정의할 때 사용합니다. proxy를 사용하게 되면 기존 객체를 래핑하고 객체의 속성이나 메서드 에 접근하는 어떤 것이든 언터셉트 를 할 수 있습니다. 심지어 사전에 정의된 속성이 아니여도 가능합니다.!! 또한 Vue 3 부터는 Object.defineProperty 이 아닌 proxy 로 작업되고 있습니다.

사용방법

new Proxy(target, handler);

targetproxy로 래핑할 객체를 넣어줍니다. 기본객체가 될수도 있고 proxy를 넣어줄 수도 있습니다. handler 는 객체의 기본적인 동작(접근, 할당, 순회 등등) 의 작업이 수행될때 Proxy의 동작을 정의하는 함수 객체를 넣어줍니다. 여기서 지정가능한 함수 객체는 13개로 다음과 같습니다.

handler 정의 함수

  • get
  • set
  • has
  • defineProperty
  • deleteProperty
  • construct
  • apply
  • getPrototypeOf
  • setPrototypeOf
  • isExtensible
  • preventExtensions
  • getOwnPropertyDescriptor
  • ownKeys

이번 글에서는 해당 모든 정의 함수를 다루지 않기때문에 나머지는 Proxy MDN 을 참고 하시면 됩니다.

get

get은 속성을 조회할때 호출되는 함수입니다.

  const person = new Proxy({}, {
        get: function (target, prop) {
          return target[prop]+' 호출 가로채기!!';
        },
      });

      person.name = 'sungin';
      console.log(person.name); // sungin 호출 가로채기!!

위의 예시 코드 처럼 닷노테이션(.) 으로 속성을 조회할때 이를 가로채서 추가작업을 할 수 있습니다. target 은 해당 객체를 의미하고 prop 은 조회할때의 해당 속성의 의미합니다.

set

set은 속성에 값을 할당할때 호출되는 함수입니다.

   const person = new Proxy({}, {
        set: function (obj, prop, value) {
          obj[prop] = value +'-set!!';
          console.log(value +'-set!!');
          return true;
        }
      });

      person.name = 'sungin'; // sungin-set!!

https://image.woolta.com/3fec11a0caf6223b.png

위의 예제를 보면 name 속성에 값을 할당할떄 이를 가로채서 실행되는 모습을 볼 수 있습니다. 또한 위의 두가지 예시인 getset의 예제를 보면 가장 놀라운 부분은 proxy 에는 아무 속성이 없는 빈객체로 설정하였으나 이상태에서 새로운 속성을 할당해도 이를 캐치하고 수행한다는 점입니다.!!

또한 set에서는 유효성 검사를 진행하는 식의 활용도 생각할 수 있습니다.

set을 활용한 유효성 검사

 const person = new Proxy({}, {
        
        set: function (obj, prop, value) {

          const ageValidation = prop === 'age' && !Number.isInteger(value);
          if (ageValidation) {
            throw new TypeError('나이는 숫자로 입력해야 합니다.');
          }
          
          obj[prop] = value +'set!!';
          return true;
        }
      });

      person.age = 23;
      person.age = '스물셋'; // TypeError 나이틑 숫자로 입력해야 합니다.!!

deleteProperty

deleteProperty는 객체 속성을 삭제할때 호출되는 함수입니다. 이를 통해 삭제하면 안되는 속성을 체크해서 삭제를 못하게 하는등의 활용이 가능합니다.

const person = new Proxy({}, {
        deleteProperty: function(target, prop) {
          const isName = prop === 'name';
         
          if(isName)
            delete target[prop];
          
          return true;
        }
      });


      person.name = 'sungin';
      person.age = 23;
      
      delete person.name;
      delete person.age; // name 속성이 아니기때문에 삭제되지 않습니다.
      console.log(person); // {age: 23}

defineProperty

definePropertyObject.definePropertyReflect.defineProperty 가 호출될때 이를 가로채서 실행하는 함수입니다.

 const person = new Proxy({}, {
         defineProperty: function (target, prop, descriptor) {
          console.log('called: ' + prop);
          console.log(target);
          return true;
        }
      });

Object.defineProperty(person, 'weight', {weight: 70, sex: 'man'});

또한 construct 는 생성자를 호출할때 apply 는 함수를 호출할때 실행됩니다. 이러한 특징들을 이용해서 읽기전용 객체를 만들거나 양방향 바인딩 또는 로깅 or 디버그 등 여러곳에서 다양하게 사용할 수 있는 장점이 존재합니다.

참고

Copyright © 2018 woolta.com

gommpo111@gmail.com