
ES6(ECMAScript 2015) – 프록시와 리플렉션 – 0 – 프록시(Proxy) 객체
프록시(Proxy) 객체란 무엇인가요?
프록시(Proxy) 객체는 ES6(ECMAScript 2015)에서 도입된 기능으로, 다른 객체의 동작을 가로채고 커스텀 로직을 적용할 수 있게 해줍니다. 프록시는 객체 사이에서 중개자 역할을 하며, 객체에 접근하는 것을 가로채어 특정 동작을 수행하거나 제어할 수 있습니다.
프록시 객체는 대상 객체를 감싸는 래퍼(wrapper) 역할을 합니다. 이 래퍼는 대상 객체에 접근하는 모든 요청을 가로채고 필요한 경우 수정하거나 대체할 수 있습니다. 이렇게 프록시를 통해 객체에 대한 접근을 제어할 수 있기 때문에 객체의 동작을 동적으로 수정하거나 모니터링할 수 있습니다.
프록시(Proxy) 객체의 예시
예를 들어, 프록시를 사용하여 객체의 속성에 접근할 때 특정 로그를 남기는 기능을 추가해보겠습니다.
const targetObject = {
name: 'John',
age: 30
};
const handler = {
get(target, property, receiver) {
console.log(`속성에 접근 중: ${property}`);
return Reflect.get(target, property, receiver);
}
};
const proxyObject = new Proxy(targetObject, handler);
console.log(proxyObject.name);
console.log(proxyObject.age);
위의 코드에서 targetObject
는 원본 객체이고, handler
는 프록시 객체의 동작을 정의한 핸들러입니다. handler
는 get
메서드를 가지고 있어 프록시 객체의 속성에 접근할 때마다 해당 속성 이름을 로그에 출력하도록 설정하였습니다.
new Proxy(targetObject, handler)
를 통해 proxyObject
를 생성하고, proxyObject
의 속성에 접근하면 핸들러의 get
메서드가 실행되며 로그가 출력됩니다. 이를 통해 프록시를 사용하여 객체의 속성에 접근하고 원하는 로직을 수행할 수 있습니다.
프록시는 다양한 동작을 가로챌 수 있으며, 접근자(getter), 설정자(setter), 함수 호출, 속성 삭제 등을 가로챌 수 있습니다. 자세한 내용은 핸들러 객체의 다양한 메서드를 활용하여 제어할 수 있습니다.
프록시(Proxy) 객체의 활용 예시
프록시 객체는 객체의 동작을 변경하거나 가로챌 수 있는 강력한 기능을 제공합니다. 이를 활용하여 다양한 상황에서 유용하게 사용할 수 있습니다.
1. 속성 값의 유효성 검사
프록시를 사용하여 객체의 속성 값에 유효성 검사를 적용할 수 있습니다. 예를 들어, 특정 속성에 문자열만 할당하고자 할 때 프록시를 활용할 수 있습니다.
const user = {
name: '',
age: 25
};
const handler = {
set(target, property, value, receiver) {
if (property === 'name' && typeof value !== 'string') {
throw new Error('이름은 문자열이어야 합니다.');
}
return Reflect.set(target, property, value, receiver);
}
};
const proxyUser = new Proxy(user, handler);
proxyUser.name = 'John'; // 유효한 값, 문제 없음
console.log(proxyUser.name); // "John"
proxyUser.name = 123; // 유효하지 않은 값, 에러 발생
console.log(proxyUser.name); // 이 줄은 실행되지 않음
위의 코드에서 handler
의 set
메서드를 사용하여 name
속성에 할당되는 값이 문자열인지 확인하고, 그렇지 않을 경우 에러를 발생시킵니다. 이렇게 프록시를 활용하면 객체의 속성 값에 제약을 두거나 특정 규칙을 적용할 수 있습니다.
2. 캐싱 기능 추가
프록시를 사용하여 함수의 결과를 캐싱하는 기능을 추가할 수 있습니다. 함수의 결과를 한 번 계산한 후, 같은 인자에 대해 다시 호출될 때는 캐싱된 결과를 반환하도록 프록시를 설정할 수 있습니다.
function expensiveOperation(n) {
console.log('계산 중...');
// 복잡한 계산 로직
return n * 2;
}
const cache = {};
const handler = {
apply(target, thisArg, args) {
const argKey = JSON.stringify(args);
if (argKey in cache) {
console.log('캐시된 결과 반환');
return cache[argKey];
}
const result = Reflect.apply(target, thisArg, args);
cache[argKey] = result;
return result;
}
};
const proxyExpensiveOperation = new Proxy(expensiveOperation, handler);
console.log(proxyExpensiveOperation(5)); // 캐시되지 않음, 계산 중...
console.log(proxyExpensiveOperation(5)); // 캐시된 결과 반환
위의 코드에서 handler
의 apply
메서드를 사용하여 함수 호출을 가로채고, 함수의 인자를 기반으로 캐시된 결과를 확인하고 반환하도록 설정했습니다. 이를 통해 계산 비용이 많이 드는 연산의 결과를 한 번 계산한 후, 이후 호출에서는 캐시된 결과를 사용할 수 있습니다.
프록시를 사용하여 객체의 동작을 가로채고 제어하는 방법은 다양합니다. 위에서 소개한 예시 이외에도 프록시를 활용하여 로깅, 성능 측정, 접근 제어 등 다양한 기능을 구현할 수 있습니다.
프록시(Proxy) 객체 사용 시 주의해야 할 점
프록시 객체를 사용할 때 몇 가지 주의할 점이 있습니다.
-
프록시 객체는 원본 객체를 감싸는 래퍼로써, 원본 객체와 동일한 인터페이스를 제공해야 합니다. 즉, 프록시 객체는 원본 객체와 같은 속성과 메서드를 가지고 있어야 합니다.
-
프록시 객체의 핸들러 메서드는 프록시 객체 자신의 속성으로 정의되지 않아야 합니다. 그렇지 않으면 핸들러 메서드 내에서
this
를 사용할 때 예기치 않은 동작이 발생할 수 있습니다. -
프록시 객체를 사용하는 도중 예외가 발생하면, 예외가 핸들러로 전파되어야 합니다. 예외를 무시하거나 처리하지 않으면 예외의 원인을 파악하기 어려울 수 있습니다.
-
프록시 객체는 대상 객체의 동작을 가로채기 때문에 성능에 영향을 줄 수 있습니다. 따라서 프록시 객체를 사용할 때 성능에 주의해야 합니다. 불필요한 추가 작업이 없도록 신중하게 구현해야 합니다.
프록시 객체를 사용하면 객체의 동작을 가로채고 커스텀 로직을 적용할 수 있습니다. 이를 통해 유효성 검사, 캐싱, 로깅 등 다양한 기능을 추가하거나 객체에 대한 접근을 제어할 수 있습니다. 프록시는 ES6에서 도입된 강력한 기능이며, 자바스크립트 개발에서 유용하게 활용될 수 있습니다.