프록시 패턴
프록시 패턴은 다른 객체의 기능을 대리하거나 접근을 제어하는 디자인 패턴이다. 이 패턴은 클라이언트가 실제 객체(RealSubject)를 직접 호출하지 않고, 대신 프록시(Proxy) 객체를 통해 요청을 중계한다. 이를 통해 RealSubject에 대한 접근을 제어하거나 추가적인 기능을 제공할 수 있다.
구조
- Subject - RealSubject와 Proxy가 구현해야 할 메소드를 정의한다. 클라이언트는 이 인터페이스를 통해 RealSubject 또는 Proxy와 상호 작용한다.
- RealSubject - 실제로 서비스를 제공하는 클래스. Proxy는 이 클래스의 인스턴스에 대한 요청을 중계한다.
- Proxy -RealSubject 클래스의 기능을 대리하는 역할. Proxy는 RealSubject의 인스턴스를 내부적으로 유지하며, 클라이언트로부터 요청을 받으면 이를 RealSubject에 전달하기 전에 필요한 처리(예: 접근 제어, 지연 로딩 등)를 수행한다.
- Client -Subject 인터페이스를 통해 RealSubject 또는 Proxy와 상호 작용한다. 클라이언트는 실제로 어떤 객체(RealSubject 또는 Proxy)와 상호 작용하는지 알지 못한다.
기본 인터페이스
// Subject 인터페이스 정의
public interface ISubject
{
void Request();
}
// RealSubject 클래스 정의
public class RealSubject : ISubject
{
public void Request()
{
Console.WriteLine("RealSubject: Handling Request.");
}
}
// Proxy 클래스 정의
public class Proxy : ISubject
{
private RealSubject _realSubject;
public Proxy(RealSubject realSubject)
{
_realSubject = realSubject;
}
public void Request()
{
if (CheckAccess())
{
_realSubject.Request();
LogAccess();
}
}
private bool CheckAccess()
{
// 여기서는 단순히 접근 권한이 있다고 가정합니다.
// 실제 애플리케이션에서는 접근 권한을 체크하는 로직이 들어갈 수 있습니다.
Console.WriteLine("Proxy: Checking access prior to firing a real request.");
return true;
}
private void LogAccess()
{
Console.WriteLine("Proxy: Logging the time of request.");
}
}
// Main 클래스
class Client
{
static void Main(string[] args)
{
Console.WriteLine("Client: Executing the client code with a real subject:");
RealSubject realSubject = new RealSubject();
realSubject.Request();
Console.WriteLine();
Console.WriteLine("Client: Executing the same client code with a proxy:");
Proxy proxy = new Proxy(realSubject);
proxy.Request();
}
}
Client: Executing the client code with a real subject:
RealSubject: Handling Request.
Client: Executing the same client code with a proxy:
Proxy: Checking access prior to firing a real request.
RealSubject: Handling Request.
Proxy: Logging the time of request.
왜 사용해야 할까?
프록시(Proxy)란 단어는 대리자, 대리인, 대용물 등 무엇인가를 대체한다는 뜻이다. 프록시 패턴은 이름에 맞게 원본 객체를 그대로 사용하지 않고 대신할 대리자를 만들어 원본을 숨기는 걸 목표로 한다.
또한 프록시 패턴은 민감한 정보를 다루는 객체에 대한 접근을 제한할 수 있다. 프록시를 사용하여 사용자의 권한을 확인하거나 객체에 대한 요청을 필터링하거나 검증할 수 있으며, 이는 잘못된 요청으로 인한 오류를 줄이는 데 도움이 된다.
public class SecurityProxy : ISubject
{
private RealSubject _realSubject;
public SecurityProxy(RealSubject realSubject)
{
_realSubject = realSubject;
}
public void Request()
{
//사용자의 제어 가능 여부를 체크
if (CheckAccess())
{
_realSubject.Request();
}
else
{
Console.WriteLine("Access Denied");
}
}
private bool CheckAccess()
{
// 권한 혹은 접근에 대한 제어
}
}
또한 기능 추가를 통해 기존 객체를 수정하지 않고도 새로운 기능을 도입할 수 있다. 프록시 패턴은 원본 객체와 집합 관계를 가지며, 이를 통해 원본 객체의 기능을 사용하되, 추가 기능을 실행하고 클라이언트에게 제공할 수 있다. 예를 들어, 객체의 메서드 호출 전후에 로깅을 수행하는 프록시를 사용하여 디버깅과 모니터링을 간소화할 수 있다.
public class LoggingProxy : ISubject
{
private RealSubject _realSubject;
public LoggingProxy(RealSubject realSubject)
{
_realSubject = realSubject;
}
public void Request()
{
LogRequest();
_realSubject.Request();
LogResponse();
}
private void LogRequest()
{
// 요청 로깅
}
private void LogResponse()
{
// 응답 로깅
}
}
장점
- 클라이언트는 Proxy를 통해 RealSubject를 사용하는 것이지만, 이를 인식하지 못하도록 숨긴다.
- 클라이언트가 RealSubject에 직접 접근하는 것을 방지하고, 접근 제어를 통해 보안을 강화할 수 있다.
- 기존 클래스를 수정하지 않고 추가 기능을 부여할 수 있다.
- RealSubject의 생성을 지연시켜 리소스를 절약하고, 성능을 향상시킬 수 있다.
단점
- 프록시 클래스를 추가함으로써 코드의 복잡성이 증가할 수 있다.
- Proxy를 거치는 과정에서 약간의 시간 지연이 발생할 수 있다.
참고자료
'프로그래밍 이론 > 디자인 패턴' 카테고리의 다른 글
14. [Design Pattern] 커맨드(Command) 패턴 (0) | 2024.01.09 |
---|---|
13. [Design Pattern] 책임 연쇄(Chain of Responsibility) 패턴 (1) | 2024.01.06 |
11. [Design Pattern] 플라이웨이트(Flyweight) 패턴 (0) | 2023.12.27 |
10. [Design Pattern] 퍼사드(Facade) 패턴 (0) | 2023.12.25 |
09. [Design Pattern] 데코레이터(Decorator) 패턴 (1) | 2023.12.10 |