FE 지식_6. Proxy

Derek·2023년 3월 5일
1

Programmers_JS_Study_FE

목록 보기
6/6
post-thumbnail

Proxy란?

Proxy 는 특정 객체를 감싸 프로퍼티 읽기, 쓰기와 같은 객체에 가해지는 작업을 중간에서 가로채는 객체다.

가로채진 작업은 Proxy 자체에서 처리되기도 하고, 원래 객체가 처리하도록 그대로 전달되기도 한다.

문법

let proxy = new Proxy(target, handler)

인자 설명
target – 감싸게 될 객체. 함수를 포함한 모든 객체가 가능.
handler – 동작을 가로채는 메서드인 '트랩(trap)'이 담긴 객체로, 여기서 proxy를 설정.

예시 - No TRAP

let target = {};
let proxy = new Proxy(target, {}); // 빈 핸들러

proxy.test = 5; // 프락시에 값을 씁니다. -- (1)
alert(target.test); // 5, target에 새로운 프로퍼티가 생겼네요!

alert(proxy.test); // 5, 프락시를 사용해 값을 읽을 수도 있습니다. -- (2)

for(let key in proxy) alert(key); // test, 반복도 잘 동작합니다. -- (3)

위 예시의 Proxy 엔 트랩( handler )이 없기 때문에 proxy 에 가해지는 모든 작업은 target에 전달됨.

  1. proxy.test= 를 이용해 값을 쓰면 target에 새로운 값이 설정됨.
  2. proxy.test 를 이용해 값을 읽으면 target에서 값을 읽음.
  3. proxy 를 대상으로 반복 작업을 하면 target에 저장된 값이 반환됨.

예시 - TRAP 활용

  • Proxy 의 트랩 (handler) 은 내부 메서드의 호출을 가로챔.
    • get, set 행위의 내부 메서드를 말함.

GET

let numbers = [0, 1, 2];

numbers = new Proxy(numbers, {
  get(target, prop) {
    if (prop in target) {
      return target[prop];
    } else {
      return 0; // 기본값
    }
  }
});

alert( numbers[1] ); // 1
alert( numbers[123] ); // 0 (해당하는 요소가 배열에 없으므로 0이 반환됨)

존재하지 않는 요소를 읽으려고 하면 배열은 원래 undefined 을 반환함.

하지만 예시에선 배열(객체)을 Proxy 로 감싸 존재하지 않는 요소를 읽으려고 할 때 0이 반환되도록 함.

let dictionary = {
  'Hello': '안녕하세요',
  'Bye': '안녕히 가세요'
};

alert( dictionary['Hello'] ); // 안녕하세요
alert( dictionary['Welcome'] ); // undefined 출력.



// 하지만 이를 Proxy를 활용한다면...


let dictionary = {
  'Hello': '안녕하세요',
  'Bye': '안녕히 가세요'
};

dictionary = new Proxy(dictionary, {
  get(target, phrase) { // 프로퍼티를 읽기를 가로챔.
    if (phrase in target) { // 조건: 사전에 구절이 있는 경우
      return target[phrase]; // 번역문을 반환.
    } else {
      // 구절이 없는 경우엔 구절 그대로를 반환.
      return phrase;
    }
  }
});

// 사전에 없는 구절을 입력하면 입력값이 그대로 반환됨.
alert( dictionary['Hello'] ); // 안녕하세요
alert( dictionary['Welcome to Proxy']); // Welcome to Proxy (입력값이 그대로 출력됨)
// undefined가 나오지 않음!

dictionary 에 존재하지 아니한 값에 접근할때 (GET) 기본동작이 아닌 다른 동작을 handler 를 통해 구현.

SET

숫자만 저장할 수 있는 배열을 만들고 싶다고 가정하자.
숫자형이 아닌 값을 추가하려고 하면 에러가 발생하도록 해야함.

let numbers = [];

numbers = new Proxy(numbers, { // (*)
  set(target, prop, val) { // 프로퍼티에 값을 쓰는 동작을 가로챔.
    if (typeof val == 'number') {
      target[prop] = val;
      return true;
    } else {
      return false;
    }
  }
});

numbers.push(1); // 추가 성공.
numbers.push(2); // 추가 성공.
alert("Length is: " + numbers.length); // 2

numbers.push("test"); // Error: 'set' on proxy
// 윗 줄에서 에러 발생 -> 이후 코드 실행 불가.
  • pushunshift 같이 배열에 값을 추가해주는 메서드들은 내부에서 Set 을 사용하고 있기 때문에 메서드를 오버라이드 하지 않아도 Proxy 가 동작을 가로채고 값을 검증함.

⚠️ 주의점


true 를 잊지 말고 반환해야한다!
set 트랩을 사용할 땐 값을 쓰는 것이 성공했을 때 반드시 true를 반환해줘야 함.


true를 반환하지 않았거나 falsy한 값을 반환하게 되면 TypeError가 발생함.

profile
Whereof one cannot speak, thereof one must be silent.

0개의 댓글