paint-brush
JavaScript에서 프록시의 힘 이해하기~에 의해@aleksandrguzenko
6,168 판독값
6,168 판독값

JavaScript에서 프록시의 힘 이해하기

~에 의해 Aleksandr Guzenko9m2023/03/29
Read on Terminal Reader
Read this story w/o Javascript

너무 오래; 읽다

JavaScript의 프록시는 다른 객체에 대해 수행되는 기본 작업을 수정하고 사용자 정의할 수 있는 객체 생성을 허용하는 기능입니다. 프록시는 다른 개체를 포함하고 해당 개체에 대한 액세스, 할당, 삭제 등의 기본 작업을 가로채는 개체입니다. 이 기사에서는 구문, 속성, 일반적인 응용 프로그램, 강점, 제한 사항 및 권장 접근 방식을 다루면서 JavaScript의 Proxy 기능을 자세히 설명합니다.
featured image - JavaScript에서 프록시의 힘 이해하기
Aleksandr Guzenko HackerNoon profile picture
0-item

수년에 걸쳐 JavaScript는 강력하고 적응력이 뛰어난 프로그래밍 언어로 성장했으며 개발자의 변화하는 요구 사항을 충족하기 위해 끊임없이 발전했습니다.


상대적으로 최근의 발전 중 하나는 프로그래머가 다른 개체의 주요 작업을 가로채고 수정할 수 있는 강력하고 유연한 개체를 만들 수 있도록 하는 프록시 개체입니다.


이 기사에서는 구문, 속성, 일반적인 응용 프로그램, 강점, 제한 사항, 예시 사례 및 권장 접근 방식을 다루면서 JavaScript 의 Proxy 기능을 자세히 살펴봅니다.


프록시란 무엇입니까?

프록시는 다른 개체를 포함하고 해당 개체에 대한 속성 액세스, 할당 및 삭제와 같은 기본 작업을 가로채는 개체입니다. 프록시는 개발자가 더욱 다양하고 강력한 코드를 작성할 수 있도록 지원하는 JavaScript의 중요한 측면입니다.


이 기사의 목표는 구문, 특성, 이점, 단점, 예시 및 권장 기술을 포함하여 JavaScript의 Proxy에 대한 포괄적인 이해를 제공하는 것입니다.

프록시의 구문 및 속성

JavaScript의 프록시는 다른 객체에 대해 수행되는 기본 작업을 수정하고 사용자 정의할 수 있는 객체 생성을 허용하는 기능입니다.


프록시 객체 생성

프록시 객체를 설정하려면 대상 객체와 핸들러 객체라는 두 가지 구성 요소가 필요합니다. 대상 객체는 작업을 가로채는 객체이고, 핸들러 객체는 이러한 작업을 포착하는 데 사용되는 트랩이나 메서드를 보유하는 역할을 담당합니다.


다음은 기본 프록시 개체를 만드는 방법을 보여주는 예입니다.

 const target = { name: 'John', age: 25, }; const handler = { get: function(target, prop) { console.log(`Getting property ${prop}`); return target[prop]; }, }; const proxy = new Proxy(target, handler); console.log(proxy.name); // Getting property name // John


이 예에서는 이름과 나이라는 두 가지 특성을 가진 대상 개체를 생성합니다. 또한 대상 객체의 속성을 읽으려는 모든 노력을 캡처하기 위한 get 트랩이 있는 핸들러 객체를 생성합니다. 그런 다음 Proxy 생성자에 대상 및 핸들러 개체를 제공하여 Proxy 개체를 생성합니다. 마지막으로 get 트랩을 호출하고 콘솔에 메시지를 출력하는 Proxy 객체의 name 속성을 검색합니다.


함정과 그 행동



트랩은 대상 개체에 대한 작업을 가로채는 메서드입니다. get, set, has, deleteProperty 등을 포함하여 Proxy 개체와 함께 사용할 수 있는 몇 가지 트랩이 있습니다.


다음은 가장 일반적으로 사용되는 트랩에 대한 간략한 개요입니다.


  1. get : 이 트랩은 대상 개체의 속성을 읽으려는 시도를 차단합니다. 대상 개체와 액세스되는 속성이라는 두 가지 인수를 사용합니다. 트랩은 속성 값을 반환합니다.


  2. set : 이 트랩은 대상 객체에 속성을 설정하려는 모든 노력을 포착합니다. 여기에는 대상 개체 자체, 설정 중인 속성, 해당 속성의 업데이트된 값이라는 세 가지 매개 변수가 필요합니다. 메커니즘에는 설정된 값을 변경하는 기능이 있거나 값 설정을 금지하는 오류를 생성할 수 있습니다.


  3. has : 이 트랩은 대상 객체에 속성이 존재하는지 확인하려는 시도를 차단합니다. 대상 개체와 확인 중인 속성이라는 두 가지 인수를 사용합니다. 트랩은 속성이 존재하는지 여부를 나타내는 부울 값을 반환합니다.


  4. deleteProperty : 이 트랩은 대상 개체에서 속성을 삭제하려는 시도를 차단합니다. 대상 개체와 삭제되는 속성이라는 두 가지 인수를 사용합니다. 트랩은 속성을 삭제하거나 속성이 삭제되는 것을 방지하기 위해 오류를 발생시킬 수 있습니다.


취소 가능한 프록시

프록시 개체는 무효화될 수 있는 매력적인 특성을 가지고 있어 해당 트랩이 더 이상 대상 개체에 대한 작업을 가로채지 못하게 됩니다. 무효화될 수 있는 프록시 객체를 생성하려면 Proxy.revocable() 함수를 활용하세요.


예는 다음과 같습니다.

 const target = { name: 'John', age: 25, }; const handler = { get: function(target, prop) { console.log(`Getting property ${prop}`); return target[prop]; }, }; const {proxy, revoke} = Proxy.revocable(target, handler); console.log(proxy.name); // Getting property name // John revoke(); console.log(proxy.name); // Uncaught TypeError: Cannot perform 'get' on a proxy that has been revoked


이 예에서는 Proxy.revocable() 메서드를 사용하여 취소 가능한 프록시 개체를 만듭니다. 그런 다음 get 트랩을 트리거하고 콘솔에 메시지를 기록하는 Proxy 객체의 name 속성에 액세스합니다. 그런 다음 revoke() 메서드를 사용하여 Proxy 개체를 취소합니다. 즉, Proxy 개체의 속성에 액세스하려는 추가 시도는 실패합니다.


프록시를 통한 상속

Proxy 객체의 또 다른 흥미로운 기능은 JavaScript에서 상속 패턴을 구현하는 데 사용할 수 있다는 것입니다. 프록시 객체를 다른 객체의 프로토타입으로 사용하면 속성 조회를 가로채고 프로토타입 체인의 동작을 사용자 정의할 수 있습니다.


예는 다음과 같습니다.

 const parent = { name: 'John', }; const handler = { get: function(target, prop) { console.log(`Getting property ${prop}`); if (!(prop in target)) { return Reflect.get(parent, prop); } return target[prop]; }, }; const child = new Proxy({}, handler); console.log(child.name); // Getting property name // John child.name = 'Bob'; console.log(child.name); // Getting property name // Bob console.log(parent.name); // John


이 예에서는 상위 개체가 정의되고 이름 특성이 있습니다. 그런 다음 하위 개체의 속성에 대한 읽기 요청을 방지하는 get 트랩을 사용하여 핸들러 개체를 만듭니다. 트랩은 자식 개체에 속성이 없는 경우 Reflect.get() 메서드를 사용하여 부모 개체로 대체합니다.


그런 다음 프록시 객체를 프로토타입으로 사용하고 핸들러 객체를 핸들러로 사용하여 하위 객체를 만듭니다. 마지막으로, 트랩 가져오기 및 설정을 시작하고 메시지를 콘솔에 기록하는 하위 개체의 이름 속성에 액세스하고 변경합니다.

Proxy를 사용한 실제 사례

캐싱

프록시의 한 가지 사용 사례는 비용이 많이 드는 함수 호출을 캐시하는 것입니다. 이 예에서는 인수를 기반으로 함수 호출 결과를 캐시하는 Proxy 개체를 만듭니다.

 function calculateCost(price, taxRate) { console.log('Calculating cost...'); return price * (1 + taxRate); } const cache = new Map(); const proxy = new Proxy(calculateCost, { apply(target, thisArg, args) { const key = args.join('-'); if (cache.has(key)) { console.log('Returning cached result...'); return cache.get(key); } else { const result = Reflect.apply(target, thisArg, args); cache.set(key, result); return result; } }, }); console.log(proxy(10, 0.2)); // Calculating cost... 12 console.log(proxy(10, 0.2)); // Returning cached result... 12 console.log(proxy(20, 0.2)); // Calculating cost... 24 console.log(proxy(20, 0.3)); // Calculating cost... 26 console.log(proxy(20, 0.3)); // Returning cached result... 26

이 예에서는 가격과 세율을 가져와 세금과 함께 비용을 반환하는 calculateCost 라는 함수를 정의합니다. 그런 다음 Map 클래스를 사용하여 캐시 개체를 만듭니다.


다음으로, apply 트랩을 사용하여 함수 호출을 가로채는 proxy 라는 프록시 개체를 만듭니다. apply 트랩은 함수가 호출될 때마다 호출되며 함수 인수를 배열로 받습니다. 인수를 사용하여 캐시 키를 생성하고 결과가 이미 캐시에 있는지 확인합니다. 그렇다면 캐시된 결과를 반환합니다. 그렇지 않으면 결과를 계산하여 캐시에 저장합니다.


마지막으로, 서로 다른 인수를 사용하여 proxy 함수를 호출하고 동일한 인수를 사용하는 후속 호출에 대한 결과가 캐시에 저장되는 것을 관찰합니다.

확인

프록시의 또 다른 사용 사례는 객체 속성의 유효성을 검사하는 것입니다. 이 예에서는 문자열 속성의 길이를 확인하는 Proxy 개체를 만듭니다.

 const user = { name: 'John', password: 'secret', }; const proxy = new Proxy(user, { set(target, prop, value) { if (prop === 'password' && value.length < 8) { throw new Error('Password must be at least 8 characters long'); } target[prop] = value; return true; }, }); console.log(proxy.name); // John console.log(proxy.password); // secret proxy.password = '12345678'; console.log(proxy.password); // 12345678 proxy.password = '123'; // Error


이 예에서는 namepassword 속성을 사용하여 user 라는 개체를 정의합니다. 그런 다음 set Trap을 사용하여 속성 할당을 가로채는 proxy 라는 프록시 개체를 만듭니다. set Trap은 속성이 할당될 때마다 호출되며 속성 이름, 새 값 및 대상 개체를 받습니다.


우리는 할당된 속성이 password 속성인지, 값의 길이가 8자 미만인지 확인하기 위해 set Trap을 사용합니다. 그렇다면 오류가 발생합니다. 그렇지 않으면 대상 개체에 속성 값을 설정합니다.


우리는 proxy 객체를 활용하여 password 속성에 다양한 값을 할당하고 길이가 8자 미만인 모든 값은 오류를 유발한다는 점에 주목합니다.

벌채 반출

프록시의 또 다른 일반적인 사용 사례는 객체 속성 액세스 및 할당을 기록하는 것입니다. 이 예에서는 속성 액세스 및 할당을 기록하는 Proxy 개체를 만듭니다.

 const user = { name: 'John', email: '[email protected]', }; const proxy = new Proxy(user, { get(target, prop) { console.log(`Getting ${prop} property`); return target[prop]; }, set(target, prop, value) { console.log(`Setting ${prop} property to ${value}`); target[prop] = value; return true; }, }); console.log(proxy.name); // Getting name property -> John proxy.email = '[email protected]'; // Setting email property to [email protected] console.log(proxy.email); // Getting email property -> [email protected]

이 예에서는 nameemail 속성을 가진 user 라는 개체를 정의합니다. 그런 다음 getset 트랩을 사용하여 속성 액세스 및 할당을 가로채는 proxy 라는 프록시 개체를 만듭니다.


get 트랩은 속성에 액세스할 때마다 호출되며 속성 이름과 대상 개체를 받습니다. 이 예에서는 속성이 액세스되고 있음을 나타내는 메시지를 콘솔에 기록한 다음 대상 개체에서 속성 값을 반환합니다.


set Trap은 속성이 할당될 때마다 호출되며 속성 이름, 새 값 및 대상 개체를 받습니다. 이 예에서는 속성이 할당되고 있음을 나타내는 메시지를 콘솔에 기록한 다음 대상 개체에 속성 값을 설정합니다.


마지막으로 proxy 객체를 사용하여 다양한 속성에 액세스하고 할당하며 메시지가 콘솔에 기록되는 것을 관찰합니다.

프록시의 장점과 한계

프록시의 장점

  1. 사용자 정의 가능한 동작 : 프록시 객체를 사용하면 다른 객체에 대한 기본 작업을 가로채고 사용자 정의할 수 있으므로 액세스 제어, 캐싱, 로깅과 같은 고급 기능을 만들 수 있습니다.


  2. 상속 : 프록시 개체는 JavaScript에서 상속 패턴을 구현하는 기능을 제공하므로 보다 다양하고 확장 가능한 코드를 만들 수 있습니다.


  3. Revocable : 프록시 객체는 생성된 후 비활성화하거나 취소할 수 있으므로 프록시 객체의 범위를 제한하거나 보안상의 이유로 유용합니다.


프록시의 한계

  1. 프록시가 오랫동안 우리와 함께 있었다는 사실에도 불구하고 모든 브라우저 버전이 이 기능을 지원할 수 있는 것은 아닙니다.


  2. 더욱이, 프록시를 사용하면 특히 프록시를 너무 자주 사용하는 경우 애플리케이션 성능에 부정적인 영향을 미칠 수 있습니다.


  3. 프록시 사용의 의미를 이해하는 것이 중요합니다. 사용자 입력의 중요한 유효성 검사와 같이 애플리케이션에 중요한 순간에는 신뢰해서는 안 됩니다.

프록시 사용 모범 사례

제한 사항에 유의하세요 . 코드에 프록시를 구현하기 전에 프록시가 부과하는 제한 사항과 해당 제한 사항이 애플리케이션의 속도와 보안에 어떤 영향을 미칠 수 있는지 확인하세요.

프록시 객체는 코드 성능에 영향을 미칠 수 있으므로 꼭 필요한 경우에만 사용해야 합니다.


신중하게 테스트하세요 . 프록시 개체를 활용할 때는 신중하게 테스트하고 잠재적으로 예상치 못한 동작이 있는지 주의하세요.


규범 준수 : 코드를 읽고 유지 관리하기 쉽게 만들려면 프록시 개체를 구현하는 동안 허용되는 규칙과 모범 사례를 준수하세요.

결론

이 기사에서는 상속 패턴 및 취소 가능한 프록시 개체를 생성하는 기능과 같은 Proxy의 고급 기능을 자세히 설명합니다.


개발자로서의 경험 수준에 관계없이 JavaScript의 프록시를 이해하는 것은 코드를 더 높은 수준으로 끌어올리는 데 필수적입니다.


적응성과 효능으로 인해 Proxy는 복잡한 애플리케이션을 쉽게 구축하려는 JavaScript 개발자에게 중요한 도구입니다.