[JS] 자바스크립트의 Proxy

토끼는 개발개발·2023년 7월 4일
0

JavaScrpit

목록 보기
1/2
post-thumbnail

📌 1. Proxy란?

Proxy는 특정 객체를 감싸 프로퍼티 읽기, 쓰기와 같은 객체에 가해지는 작업을 중간에서 가로채는 객체로, 가로채진 작업은 Proxy 자체에서 처리되기도 하고, 원래 객체가 처리하도록 그대로 전달되기도 한다.

Proxy의 사전적 뜻은 '대리인', '대리'라는 뜻이다.
자바스크립트에서도 단어 뜻 그대로 대리인의 역할을 수행한다.

프록시 객체(Proxy object)는 대상 객체(Target object) 대신 사용된다. 대상 객체를 직접 사용하는 대신, 프록시 객체가 사용되며 각 작업을 대상 객체로 전달하고 결과를 다시 코드로 돌려준다.

이러한 방식을 통해 프록시 객체는 JavaScript의 기본적인 명령에 대한 동작을 사용자 정의 가능하도록 한다.
객체 자체가 처리하는 특정 명령을 재정의할 수 있게 되는 것이다. 이런 명령의 종류는 속성 검색, 접근, 할당, 열거, 함수 호출 등이 대표적이다.



📌 2. Proxy 사용법

//아래와 같이 정의
const proxy = new Proxy(target, handler)

프록시 객체를 생성하기 위해 new를 붙여 생성자를 호출해야 한다.
Proxy는 필수적으로 다음과 같은 2개의 인자를 받는다.

  • target : Proxy의 대상이 되는 객체(감싸질 객체). 함수를 포함한 모든 객체가 가능.
  • handler : 동작을 가로채는 메서드인 '트랩(trap)*'이 담긴 객체로, 여기서 프록시를 설정한다(예시: get 트랩은 target의 프로퍼티를 읽을 때, set 트랩은 target의 프로퍼티를 쓸 때 활성화됨).

proxy에 작업이 가해지고, handler에 작업과 상응하는 트랩이 있으면 트랩이 실행되어 프록시가 이 작업을 처리할 기회를 얻게 된다. 트랩이 없으면 target에 작업이 직접 수행된다.


💡 *트랩(Trap)이란?
동작을 가로채는 함수. 기본 명령을 재정의하기 위한 함수.


📌 3. Proxy 예제

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

proxy.test = 5; //  프록시에 값을 입력.
alert(target.test); // 5, target에 새로운 프로퍼티가 생성됨.
alert(proxy.test); // 5, 프록시를 이용해 값을 읽을 수 있음.

for(let key in proxy) alert(key); // test

프록시는 일반 객체와 다른 양상을 보이는 특수 객체** 이다. 프로퍼티가 없다.
handler가 비어있으면 proxy에 가해지는 작업은 target에 곧바로 전달된다.

트랩을 추가하면, 프록시의 기능이 활성화 된다.
프락시의 트랩은 내부 메서드의 호출을 가로챈다, 모든 내부 메서드엔 대응하는 트랩이 있다.

핸들러로 재정의 할 수 있는 함수는 다음과 같다.

[핸들러 재정의 함수]

<출처: https://meetup.nhncloud.com/posts/302 >


프록시 기능을 활성화 시켜보자. 간단하게 프로퍼티 읽기 get을 가로채보자.
프로퍼티 읽기를 가로채려면 handler에 get(target, property, receiver) 메서드가 있어야 한다.

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 (원래는 객체에 없는 프로퍼티를 호출했으므로 undefine가 호출)


💡 **특수객체(exotic object)란?
자바스크립트에서 기본과 다른 내부 동작이 있는 객체.



📌 4. Proxy를 사용하는 이유

프록시는 내부 메서드의 호출을 가로채서 재정의 한다고 했다.
왜 가로채는 것일까?
추가적으로 새로운 함수를 정의하고 사용하는 것이 아닌, 내부 메서드를 가로채서 재정의 하는 이유가 무엇일까?

우리는 자바스크립트의 내부메서드 호출에 대해 좀 더 집중해서 살펴볼 필요가 있다.
객체에 어떤 작업을 할 땐 자바스크립트 명세서에 정의된 '내부메서드'가 깊숙한 곳에서 관여한다. 프로퍼티를 읽을 땐 [[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 (원래는 객체에 없는 프로퍼티를 호출했으므로 undefine가 호출)

객체에 없는 프로퍼티를 호출했을 때, undefined가 아닌 0이 출력되었다.
자바스크립트의 내부 메서드 GET을 통해, 객체에 없는 프로퍼티를 읽으면 undefined가 출력되는 것이 당연하다.
하지만, 프록시로 0이 출력되도록 한 것이다.

이것이 프록시의 기능이다.



[참고문헌]

https://ko.javascript.info/proxy
https://meetup.nhncloud.com/posts/302


이번 프록시의 개념은 자바스크립트 초보인 내가 빠르게 이해하기엔 꽤 어려운 내용이었다.
일주일 가까이 틈틈이 인강과 포스팅을 찾아보며 내용을 채워나갔다.

어제 알던게 오늘 수정되기도 하고, 오늘 생긴 물음표가 내일 해결되기도 하는걸 느끼며 꽤나 재밌게 포스팅했다.

뷰와 자바스크립트 공식사이트를 기반으로 작성했지만, 틀린 내용이 있을 수 있다.
더 나은 이해, 수정사항이 생기면 계속 고치고 덧붙여 나가야겠다.

profile
하이 이것은 나의 깨지고 부서지는 기록들입니다

0개의 댓글