
Vue.js에서 reactive로 반응성을 주입한 데이터를 콘솔로 찍어보면 위처럼 Proxy {...} 형태로 출력한다. Proxy를 사용해서 입력한 데이터(상태)를 한 번 감싼 것이다. 이렇게 Proxy를 이용하면 객체 프로퍼티의 읽기 / 쓰기 같은 작업을 중간에 가로채서 원하는 작업을 수행하도록 할 수 있다.
const proxy = new Proxy(target, handler);
get이나 set 같은 동작을 가로채는 메서드(트랩; trap)이 담긴 객체.객체를 proxy로 감싼 후, handler에 상응하는 트랩(메서드)가 있으면 트랩이 실행된다. 트랩이 없으면 target에서 작업이 수행된다. 아래 예시에선 트랩(handler)이 비어있기 때문에 proxy에 대한 모든 작업이 target으로 전달된다.
const user = { name: 'johan', age: 30 };
const proxy = new Proxy(user, {});
console.log(proxy) // Proxy {name: 'johan', age: 30}
proxy.test = 30 // 프로퍼티 추가
for (const key in proxy) console.log(key) // name, age, test
객체에 어떤 작업을 할 때 자바스크립트 명세에 정의된 내부 매서드(Internal Method)가 관여한다. 예를들어 프로퍼티를 읽을 땐 [[Get]], 프로퍼티를 쓸 땐 [[Set]] 이라는 내부 메서드가 관여한다. 내부 메서드는 개발자가 호출할 수 없다. Proxy의 트랩은 이런 내부 메서드의 호출을 가로채며, 모든 내부 메서드엔 대응하는 트랩이 있다.
| 내부 메서드 | Proxy 핸들러(트랩) 메서드 | 핸들러(트랩) 작동 시점 |
|---|---|---|
| [[Get]] | get | 프로퍼티 조회 |
| [[Set]] | set | 프로퍼티 쓰기 |
| [[HasProperty]] | has | in 연산자 사용시 |
| [[Delete]] | deleteProperty | delete 연산자 사용시 |
| [[Call]] | apply | 함수 호출 시 |
| [[Construct]] | construct | new 연산자 사용시 |
| [[GetPrototypeOf]] | getPrototypeOf | Object.getPrototypeOf |
| [[SetPrototypeOf]] | setPrototypeOf | Object.setPrototypeOf |
| [[IsExtensible]] | isExtensible | Object.isExtensible |
| [[PreventExtensions]] | preventExtensions | Object.preventExtensions |
| [[DefineOwnProperty]] | defineProperty | Object.defineProperty Object.defineProperties |
| [[GetOwnProperty]] | getOwnPropertyDescriptor | Object.getOwnPropertyDescriptor for..in Object.keys/values/entries |
| [[OwnPropertyKeys]] | ownKeys | Object.getOwnPropertyNames Object.getOwnPropertySymbols for..in Object/keys/values/entries |
[[Set]] 메서드는 반드시 true 반환. 실패 시 false 반환[[Delete]] 메서드는 반드시 true 반환. 실패 시 false 반환[[GetPrototypeOf]] 메서드가 적용되면 프락시 타깃 객체에 [[GetPrototypeOf]] 를 적용한 것과 동일한 값 반환