[JavaScript] Proxy 객체 이해하기

서동경·2023년 3월 1일
0
post-thumbnail

🍀 Proxy

"Proxy"란 "대리"라는 의미를 가진 단어이다. Proxy는 특정 객체에서 일어나는 작업을 가로챌 수 있는 특수 객체이다.

빌트인 생성자 함수와 new 키워드를 사용해 생성할 수 있다. 그리고 두 개의 객체 파라미터를 가지는데, 첫 번째 파라미터에는 타겟 객체를 넣어주고 두 번째 파라미터에는 핸들러 객체를 넣어준다. 핸들러 객체에는 내장 메서드의 동작을 가로채 어떠한 작업을 수행하는 메서드인 트랩을 정의한다. get, set 매서드를 사용하면 읽기/할당 동작을 가로챌 수 있다.

핸들러 객체에 트랩을 정의가 완료되고 프록시 객체에 어떠한 작업을 가하면, 트랩으로 인해 프록시 객체에서 해당 작업이 처리되며 트랩에 정의된 작업이 수행된다. 타겟 객체는 원래 상태를 그대로 유지하게 되며, 타겟 객체에도 동일한 작업이 처리되기를 원한다면 트랩에서 따로 정의한다.

const targetObject = {
  name: 'DONGKYEONG',
  age: 20
};

const handler = {
  get: function (target, property) {
    console.log(`속성을 읽는 중: ${property}`);
    return target[property];
  },
  set: function (target, property, value) {
    console.log(`속성을 설정하는 중: ${property} = ${value}`);
    target[property] = value; 
  }
  // get(){}, set(){} 형태도 OK
};

const proxy = new Proxy(targetObject, handler);

proxy.name; // "속성을 읽는 중: name", 결과: 'DONGKYEONG'
proxy.age = 30; // "속성을 설정하는 중: age = 30"
console.log(proxy.age); // "속성을 읽는 중: age", 결과: 30

한편, 핸들러 객체에 트랩을 정의하지 않고 프록시 객체에 어떤 작업을 수행한다면, 타겟 객체에 그대로 작업이 처리된다. 즉, 이 경우 프록시 객체는 래퍼 역할만 수행한다.

let targetObj = {};
let proxyObj = new Proxy(targetObj, {}); // 빈 핸들러 전달

proxyObj.name = "DONGKYEONG"; // 프록시 객체에 값을 설정
console.log(targetObj.name); // dongkyeong

get, set은 어떻게 동작을 가로챌까?

객체에 어떤 작업을 수행하면 자바스크립트 명세서의 정의된 내장 메서드가 깊숙한 곳에서 관여하게 된다. 예를 들면, 객체 내 프로퍼티를 읽을 땐 [[Get]]이라는 내장 메서드가, 프로퍼티에 값을 쓸 땐 [[Set]]이라는 내장 메서드가 관여하게 된다. 이런 내장 메서드들은 명세서에만 정의되어 있기 때문에, 개발자가 직접 코드를 사용해 호출할 수는 없고 프록시의 트랩을 사용해 이러한 내장 메서드의 호출을 가로챌 수 있다.

💬 handler.get(target, property [, receiver])

프로퍼티를 읽을 때, 즉 [[Get]] 내장 메서드가 관여할 때 작동하는 메서드이다.

📌 get 핸들러의 인자

  1. target: new Proxy의 첫번째 인자로 주었던 target 객체를 가르킨다.
  2. property: 조회한 property
  3. receiver: getter가 호출될 때 this. 기본적으로는 객체 자신을 호출하지만 상속받은 객체일 경우에는 상속한 객체가 this가 된다.

💬 handler.set(target, property, value [, receiver])

프로퍼티에 값을 할당할 때, 즉 [[Set]] 내장 메서드가 관여할 때 작동하는 메서드이다.

성공하면 true, 실패하면 false를 반환한다.

📌 set 핸들러의 인자

  1. target: new Proxy의 첫번째 인자로 주었던 target 객체
  2. property: 작성한 property 이름
  3. value: 작성한 property 값
  4. receiver: setter가 호출될 때 this. 기본적으로는 객체 자신을 호출하지만 상속받은 객체일 경우에는 상속한 객체가 this가 된다.
profile
개발 공부💪🏼

0개의 댓글