proxy
단어의 뜻은 대리인입니다.
Proxy 패턴은 실제 객체에 직접 접근하는 것이 아닌, 실 객체를 대리하는 객체인 Proxy 객체를 다루는 패턴입니다.
먼저 객체를 만들고 그 객체의 Proxy 객체를 만들어봅시다.
const person = {
name: "yeony",
age: 24,
job: "frontend developer",
}
//Proxy 객체
const personProxy = new Proxy(person, {})
Proxy
객체는 프록시 인스턴스 생성(new 키워드)으로 쉽게 만들 수 있습니다.
Proxy
클래스의 구조를 살펴봅시다.
new Proxy(target, handler)
Proxy
의 첫 번째 매개변수는 프록시객체로 만들 타깃 객체입니다.
두 번째 매개변수는 핸들러
로, proxy의 행동을 정의합니다.
핸들러 객체에서 인터랙션 동작을 정의하고, 메소드를 추가할 수 있습니다.
가장 흔히 사용되는 메소드인 get
과 set
메소드를 보겠습니다.
const person = {
name: "yeony",
age: 24,
job: "frontend developer",
}
//Proxy 객체
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
return true
},
})
personProxy.name = "Nayeon"
이렇게 되면 personProxy
를 통해 person
객체가 수정됩니다.
이러한 프록시 패턴은 유효성 검사를 구현할 때 유용하게 사용할 수 있습니다.
const personProxy = new Proxy(person, {
get: (obj, prop) => {
// 원본 person 객체에 key가 존재하지 않으면 접근할 수 없도록 방지
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
}
},
})
원본 객체에 존재하지 않는 key로 접근하거나, 예상하지 못한 타입의 값을 할당하려는 경우에 proxy객체를 통해 방지할 수 있습니다. 따라서 실수를 예방함으로써 데이터의 안정성을 관리할 수 있는 패턴이 됩니다.
자바스크립트에서는 Reflect 라는 빌트인 객체를 제공합니다.
Reflect
는 중간에서 가로챌 수 있는 자바스크립트 작업에 대한 메소드를 제공합니다. 메소드 종류는 Proxy
와 동일합니다. 단, 함수 객체가 아니라 생성자로 사용은 불가능합니다.
Reflect
는 이렇게 사용합니다
// Proxy
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
},
})
// Reflect 사용
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}`)
Reflect.set(obj, prop, value)
},
})
obj[prop] = value
형태가 아니라, Reflect.get(obj, prop)
, Reflect.set(obj, prop, value)
의 형태로 작성할 수 있습니다.
Proxy는 객체의 동작을 커스터마이징할 수 있는 유용한 기능입니다. 유효성 검사, formatting, 알림, 디버깅 등에 유용합니다.
핸들러 객체에서 Proxy를 과도하게 사용하면 성능이 저하될 수 있습니다.