React처럼 변수 값 변경을 감시하기(Proxy, getter, setter)

2019년 06월 24일
notion image
<input id="debugger" type="text" value="0"> <input id="plusBtn" type="button" value="+"> <input id="minusBtn" type="button" value="-">
우선 값을 컨트롤 하고 결과를 표시하게 될 HTML 요소를 간단히 만들어준다.
 
const watcher = (variable, callback) => new Proxy(variable, { set: (obj, prop, value) => { obj[prop] = value; callback(obj); }, get: (obj, prop) => { return prop in obj ? obj[prop] : undefined; }, });
그 후 Proxy 객체를 리턴해주는 함수를 하나 작성한다.
Parameter는 Proxy 대상이 될 Object(variable)과 변경 후의 action을 지정할 callback function이다.
Proxy는 ES6에서 사용 가능하며, 첫 번째 인자인 객체 Object의 프로퍼티를 두 번째 인자인 Object로 덮어쓴다.
즉 객체에 포함된 기본 프로퍼티를 오버라이드 할 때 사용한다는 것이다.
예를 들어 getter, setter처럼 Object의 기본 기능을 Proxy를 사용하여 오버라이드 할 수 있다는 뜻이다.
따라서 위 함수는 Proxy를 이용하여 Object인 variable의 gettersetter를 재정의하여 만들어진 객체를 리턴한다.
이 외에도 get, set, has, apply, deleteProperty, defineProperty, construct 등의 기본 프로퍼티도 재정의가 가능하다.
 
let defaultState = { value: 0 }; let proxyState = watcher(defaultState, state => console.log(state)); console.log(proxyState); // Proxy { value: 0, foo: "test" } proxyState.value = 1; // { value: 1, foo: "test" }
위에서 작성한 watcher function을 이용하여 Proxy Object인 proxyState를 생성하였다.
callback function으로는 watcher function에서 return 해주는 값을 console.log 해주도록 하였다.
proxyState를 console.log를 이용하여 확인해보니 정상적으로 Proxy Object라고 표시된다.
이 후 proxyState의 value 값을 임의로 변경해보자.
 
notion image
state => console.log(state) 구문이 정상적으로 동작하였다.
위 watcher function에서 setter의 역할을 값 할당(변경) 및 callback을 호출하도록 설정하였기 때문에 callback 호출되었다.
callback은 첫 번째 인자로 현재 state를 받아올 수 있다.
 
document.getElementById('plusBtn').addEventListener('click', () => { proxyState.value++; }); document.getElementById('minusBtn').addEventListener('click', () => { proxyState.value--; });
이제, 제일 처음에 마크업 했던 HTML 태그들에 eventListener를 등록한다.
+ 버튼을 클릭하면 proxyState의 값이 증가하고 - 버튼을 클릭하면 반대로 proxyState의 값이 감소하는 내용이다.
 
let proxyState = watcher(defaultState, state => { document.getElementById('debugger').value = state.value; });
그리고 watcher의 callback 내용을 위와 같이 변경한다.
 
notion image
이렇게 되면 변수 값이 변경될 때마다 innerHTML, value, text 값을 일일히 변경하는 것이 아닌,
한 번만 지정해주면 자동으로 변경되니 매우 편리하다.