❓프록시 패턴?
프록시(proxy)는 대리인, 대리자라는 뜻으로, 다른 객체의 접근 제어를 위한 구조 디자인 패턴입니다. 객체가 전달되는 중간 단계에 대리자를 위치시켜 무언가를 수행할 수 있도록 합니다.
하나의 객체를 두 개로 나눠 재구성하여, 실체 객체를 가로챌 수 있습니다.
여기서 특징은, 두 개로 나뉜 두 객체의 인터페이스는 같다는 것입니다.
❗프록시 패턴의 예시 (JS)
// 실체 객체
class RealObject {
performAction() {
console.log("실체 객체 작동");
}
}
// 프록시 객체
class ProxyObject {
constructor(realObject) {
this.realObject = realObject;
}
performAction() {
console.log("실체 객체 작동 이전, 프록시 객체 작동");
this.realObject.performAction();
console.log("실체 객체 작동 이후, 프록시 객체 작동");
}
}
// 클라이언트 코드
const realObject = new RealObject();
const proxyObject = new ProxyObject(realObject);
proxyObject.performAction();
/*
실체 객체 작동 이전, 프록시 객체 작동
실체 객체 작동
실체 객체 작동 이후, 프록시 객체 작동
*/
동적 언어인 JS 특성상 인터페이스를 만들진 않았지만, 실체 객체와 프록시 객체 동일하게 performAction()를 가지고 있다는 것을 알 수 있습니다.
프록시 패턴을 활용하는 방법은 여러가지가 있습니다. 이 중에서 많이 사용되는 활용 용도에는 다음과 같은 것들이 있습니다.
✍️ 동적 프록시 (dynamic proxy)
동적 프록시(dynamic proxy)는 프로그램이 런타임 중에 동적으로 생성되는 프록시 객체를 말합니다. 클라이언트 코드에서는 행동을 처리하는 객체가 프록시인지 실제 객체인지 구별하지 않습니다. 이는 팩토리 패턴을 활용하여 구현할 수 있습니다.
팩토리 패턴이란 객체의 생성을 별도의 클래스로 분리하여 생성을 위임하는 패턴을 말합니다.
// 프록시 팩토리
class ProxyFactory{
getObject(){
this.real = new RealObject();
return new ProxyObject ();
}
//...
const factory = new ProxyFactory();
const proxy = factory.getObject(); // 프록시의 동적 생성
✍️ 원격 프록시 (remote proxy)
원격 프록시(remote proxy)는 가장 많이 응용하는 패턴으로, 주로 데이터 전달을 목적으로 사용합니다. 이는 어댑터 패턴과 비슷하게 보일 수 있습니다.
어댑터 패턴과의 차이점이라면 어댑터 패턴은 서로 다른 인터페이스의 호환을 맞춰주는 반면, 원격 프록시는 동일한 인터페이스를 유지한다는 것입니다.
// 실체 객체
class RealObject {
action1() {
console.log("실체 객체 action1 작동");
}
action2(){
console.log("실체 객체 action2 작동");
}
}
// 프록시 객체
class ProxyObject {
constructor(realObject) {
this.realObject = realObject;
}
action1() {
console.log("action1 은 대체되었습니다.");
}
action2(){
if(this.realObject.action2()){
this.realObject.action2()
}else{
console.log("실체 객체에 존재하는 메서드가 아닙니다.")
}
}
action3(){
if(this.realObject.action3()){
this.realObject.action3()
}else{
console.log("실체 객체에 존재하는 메서드가 아닙니다.")
}
}
}
// 클라이언트 코드
const realObject = new RealObject();
const proxyObject = new ProxyObject(realObject);
proxyObject.action1(); // action1 은 대체되었습니다.
proxyObject.action2(); // 실체 객체 action2 작동
proxyObject.action3(); // 실체 객체에 존재하는 메서드가 아닙니다.
/*
*/
예제와 같이 투과적 특성을 이용하여 객체의 행동을 대체 처리 할 수 있습니다.
✍️ 가상 프록시 (virtual proxy)
가상 프록시(virtual proxy) 는 프로그램의 실행 속도를 개선하기 위한 패턴입니다. 프록시 패턴을 이용하여 무거운 객체 생성을 잠시 유보합니다.
게으른 초기화(lazy initialization)를 이용하여 지연 시간을 줄일 수 있습니다. 게으른 초기화란, 객체의 생성에 많은 시간이 소요되는 경우, 해당 객체를 직접 요청하기 이전까지 객체의 생성을 지연시켜 불필요한 리소스 사용을 방지하는 것을 말합니다.
//... 프록시 클래스 내부
action2(){
// 게으른 객체 생성
if(!this.realObject){
this.real()
}
this.realObject.action2();
}
//무거운 객체를 생성합니다.
real(){
this.realObject = new RealObject();
}
//...
✍️ 보호용 프록시
보호용 프록시는 객체의 접근을 제어하기 위한 객체의 대리자를 제공합니다. 특정 조건을 이용하여 보안이나 안정성을 강화하는 패턴입니다.
// 프록시 클래스
class FileSystemProxy {
constructor(realFileSystem, userRole) {
this.realFileSystem = realFileSystem;
this.userRole = userRole;
}
readFile(fileName) {
if (this.userRole === "admin") {
this.realFileSystem.readFile(fileName);
} else {
console.log("접근이 거부되었습니다.");
}
}
}
// 클라이언트 코드
const realFileSystem = new FileSystem();
const adminProxy = new FileSystemProxy(realFileSystem, "admin");
adminProxy.readFile("importantDocument.txt"); // 허용
const userProxy = new FileSystemProxy(realFileSystem, "user");
userProxy.readFile("confidentialInfo.txt"); // 거부
✍️ 스마트 참조자
이것은 장식자 패턴과 유사하게 객체를 동적으로 확장 응용하는 기법입니다.
//... 프록시 클래스 내부
action2(){
console.log("추가 동작 콘솔 입니다.") // 동적 기능을 확장
this.realObject.action2();
}
//...
위와 같이 실제 코드를 직접 변경하지 않고, 추가 작업을 부여할 수 있다는 장점이 있습니다.
❗JS에서의 프록시
JS에서는 ES6에서 Proxy 객체가 추가되었습니다. 따라서 위의 코드처럼 직접 Proxy를 구현할 필요 없이 Proxy 객체를 사용하여 기본 객체를 가로채고 재정의할 수 있습니다. 자세한 사용법은 MDN을 참고하세요!
const target = {
message1: "hello",
message2: "everyone",
};
const handler1 = {};
const proxy1 = new Proxy(target, handler1);
❗결론!
프록시 패턴은 결국 “대리자”를 만들어 실체 객체의 변경을 하지 않고, 간접 적으로 제어할 수 있는 것이라는 것을 알았습니다! 객체 지향에서 중요한 ‘느슨한 결합’을 도와주는 아주 유용한 패턴이라는 것을 깨달았구요. 정말 중요한 내용 패턴이라고 생각되네요!
'개발 상식 > 디자인 패턴' 카테고리의 다른 글
[디자인 패턴] 플라이웨이트(Flyweight) 패턴 (0) | 2023.11.21 |
---|---|
[디자인 패턴] 파사드(Facade) 패턴 (0) | 2023.11.20 |
[디자인 패턴] 장식자(Decorator) 패턴 (0) | 2023.11.17 |
[디자인 패턴] 복합체(Composite) 패턴 (0) | 2023.11.15 |
[디자인 패턴] 브릿지(Bridge) 패턴 (0) | 2023.11.14 |