Proxy 객체를 활용하면 특정 객체(Object)와의 인터렉션을 조금 더 세밀하게 조작할 수 있게 된다.
Proxy 객체는 어떤 객체의 값을 설정(set)하거나 값을 조회(get)할 때 등의 인터렉션을 직접 제어할 수 있다.
객체 리터럴을 통해서 객체 person을 만들었다.
const person = {
name: 'John Doe',
age: 42,
nationality: 'American',
};
이제 해당객체와 직접 인터렉션 하는 대신 Proxy 객체와 인터렉션을 진행해야 한다.
Proxy 인스턴스를 만드는 것으로 쉽게 Proxy 객체를 생성할 수 있다.
const person = {
name: 'John Doe',
age: 42,
nationality: 'American',
};
const personProxy = new Proxy(person, {});
console.log(personProxy); // { name: 'John Doe', age: 42, nationality: 'American' }
⚠️NOTE
let proxy = new Proxy(target, handler)Proxy 객체의 두번 째 인자는
handler에 해당한다.
핸들러 객체에서 우리는 인터렉션의 종류에 따른 특정 동작들을 정의할 수 있다.
또한 여러 메서드들을 추가할 수 있는데, 일반적으로 아래에 설명하는 get과 set이다.
get : 프로퍼티에 접근하려고 할 때 실행된다. set : 프로퍼티에 값을 수정하려고 할 때 실행된다.↓↓↓그림으로 도식화 해보면 다음과 같다.↓↓↓

그림처럼 우리는 이제 person 객체와 직접 인터렉션하는 것 대신 personProxy 객체와 인터렉션 하게 된다.
personProxy 객체에 핸들러를 추가해보자. 프로퍼티를 수정하려 할 때는 앞서 말한 것과 같이 Proxy의 set메서드가 호출되므로 이 핸들러 안에서 변경 전의 값과 변경 후의 값을 콘솔로 확인할 수 있다.
프로퍼티의 값을 읽으려 할 때는 get메서드가 호출되며 해당 키와 값에 대한 메세지를 콘솔에 출력할 수 있게 된다.
const personProxy = new Proxy(person, {
get: (obj, prop) => {
console.log(`The value of ${prop} is ${obj[prop]}`)
},
set: (obj, prop, value) => {
console.log(`Changed ${prop} from ${obj[prop]} to ${value}`)
obj[prop] = value
},
})
전체 코드는 아래와 같다.
const person = {
name: "John Doe",
age: 42,
nationality: "American",
};
const personProxy = new Proxy(person, {
get: (obj, prop) => {
console.log(`The value of ${prop} is ${obj[prop]}`);
},
set: (obj, prop, value) => {
console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
obj[prop] = value;
},
});
personProxy.name;
personProxy.age = 22;
personProxy.nationality = "Korea";
console.log(person);
// logging
// The value of name is John Doe
// Changed age from 42 to 22
// Changed nationality from American to Korea
// { name: 'John Doe', age: 22, nationality: 'Korea' }
Proxy는 유효성 검사를 구현할 때 유용하다.
사용자는 person객체의
age프로퍼티를 문자열로 수정할 수 없고 name프로퍼티를 빈 문자열로 초기화 할 수 없다.person객체에 존재하지 않는 프로퍼티에 접근하려 하면 알려줄 수 있다.const personProxy = new Proxy(person, {
get: (obj, prop) => {
if (!obj[prop]) {
console.log(
`Hmm.. this property doesn't seem to exist on the target object`
)
} else {
console.log(`The value of ${prop} is ${obj[prop]}`)
}
},
set: (obj, prop, value) => {
if (prop === 'age' && typeof value !== 'number') {
console.log(`Sorry, you can only pass numeric values for age.`)
} else if (prop === 'name' && value.length < 2) {
console.log(`You need to provide a valid name.`)
} else {
console.log(`Changed ${prop} from ${obj[prop]} to ${value}.`)
obj[prop] = value
}
},
})
personProxy.nonExistentProperty;
personProxy.age = "44";
personProxy.name = "";
// logging
// Hmm.. this property doesn't seem to exist on the target object
// Sorry, you can only pass numeric values for age.
// You need to provide a valid name.
이렇게 유효하지 않은 값들을 넣으면 Proxy는 person객체를 실수로 수정하는 것을 예방해주어 데이터를 안전하게 관리할 수 있다.
JavaScript는 Reflect라는 built-in 객체를 제공하는데 Proxy와 함께 사용하면 객체를 쉽게 조작할 수 있다.
이전 예제에서는 Proxy 핸들러 내에서 {} 표기를 사용해 직접 프로퍼티를 수정하거나 읽을 수 있었는데 Reflect객체를 사용해서 Reflect 객체의 메서드는 핸들러 객체와 같은 이름의 메서드를 가질 수 있다.
obj[prop] 형태로 프로퍼티에 직접 접근하거나 obj[prop] = value 형태의 코드로 값을 수정하는 대신, Reflect.get() 혹은 Reflect.set() 을 활용할 수 있다. 각 메서드들은 핸들러의 메서드와 인자 또한 동일하다.
const person = {
name: "John Doe",
age: 42,
nationality: "American"
};
const personProxy = new Proxy(person, {
get: (obj, prop) => {
console.log(`The value of ${prop} is ${Reflect.get(obj, prop)}`);
},
set: (obj, prop, value) => {
console.log(`Changed ${prop} from ${obj[prop]} to ${value}`);
return Reflect.set(obj, prop, value);
}
});
personProxy.name;
personProxy.age = 43;
personProxy.name = "Jane Doe";
원문에 설명이 조금 부족하여서 내가 좀더 붙여 봄
저번에 Proxy에 대해 작성한 글이 있어서 첨부 함 (원문)

Proxy는 객체의 동작을 커스터마이징할 수 있는 유용한 기능이다. Proxy는 유효성 검사, 포메팅, 알림, 디버깅 등 유용하게 사용된다.
핸들러 객체에서 Proxy 를 너무 헤비하게 사용하면 앱의 성능에 부정적인 영향을 줄 수 있다. Proxy를 사용할 땐 성능문제가 생기지 않을 만한 코드를 사용하자.