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]]
를 적용한 것과 동일한 값 반환