inblog logo
|
heo-gom
    java

    프록시 패턴(Proxy Pattern)

    허성재's avatar
    허성재
    Aug 14, 2024
    프록시 패턴(Proxy Pattern)
    Contents
    프록시 패턴의 구성 요소프록시 패턴의 종류와 예시프록시 패턴의 장점
    프록시 패턴(Proxy Pattern)은 다른 객체에 대한 접근을 제어하기 위해 대리자 역할을 하는 객체를 사용하는 디자인 패턴입니다. 이 패턴은 객체의 접근을 통제하거나, 실제 객체를 대신해 간접적인 인터페이스를 제공할 때 유용합니다. 프록시는 클라이언트의 요청을 받아 실제 객체에 전달하거나, 요청을 가로채어 추가적인 작업을 수행할 수 있습니다.

    프록시 패턴의 구성 요소

    1. Subject (주체): 실제 객체와 프록시 객체가 공유하는 인터페이스입니다. 여기에는 클라이언트가 호출할 메서드들이 정의됩니다.
    1. Real Subject (실제 객체): 실제 작업을 수행하는 객체입니다.
    1. Proxy (프록시 객체): 실제 객체에 대한 접근을 제어하는 역할을 합니다.

    프록시 패턴의 종류와 예시

    1. 가상 프록시 (Virtual Proxy)

    • 목적: 실제 객체의 생성이 비용이 많이 드는 경우, 객체를 실제로 필요할 때까지 지연하여 생성합니다.
    • 예시: 큰 이미지 파일을 로드할 때 가상 프록시를 사용하여, 실제로 이미지가 필요할 때만 로드합니다.
    interface Image { void display(); } class RealImage implements Image { private String filename; public RealImage(String filename) { this.filename = filename; loadImageFromDisk(); } private void loadImageFromDisk() { System.out.println("Loading image from disk: " + filename); } @Override public void display() { System.out.println("Displaying image: " + filename); } } class ProxyImage implements Image { private RealImage realImage; private String filename; public ProxyImage(String filename) { this.filename = filename; } @Override public void display() { if (realImage == null) { realImage = new RealImage(filename); } realImage.display(); } } public class Main { public static void main(String[] args) { Image image = new ProxyImage("large_image.jpg"); image.display(); // 이미지가 처음 호출될 때 로드됨 image.display(); // 이미 로드된 이미지를 다시 표시 } }

    2. 보호 프록시 (Protection Proxy)

    • 목적: 객체에 대한 접근을 제어하여, 사용자의 권한에 따라 특정 메서드의 접근을 제한합니다.
    • 예시: 접근 제어를 위해 보호 프록시를 사용하여, 사용자의 권한에 따라 문서의 내용을 볼 수 있도록 합니다.
    interface Document { void display(); } class RealDocument implements Document { private String content; public RealDocument(String content) { this.content = content; } @Override public void display() { System.out.println("Displaying document: " + content); } } class ProtectionProxyDocument implements Document { private RealDocument realDocument; private String userRole; public ProtectionProxyDocument(String content, String userRole) { this.realDocument = new RealDocument(content); this.userRole = userRole; } @Override public void display() { if ("Admin".equals(userRole)) { realDocument.display(); } else { System.out.println("Access Denied: You do not have permission to view this document."); } } } public class Main { public static void main(String[] args) { Document document = new ProtectionProxyDocument("Confidential Report", "Guest"); document.display(); // 접근 거부 메시지 출력 Document adminDocument = new ProtectionProxyDocument("Confidential Report", "Admin"); adminDocument.display(); // 문서 내용 출력 } }

    3. 원격 프록시 (Remote Proxy)

    • 목적: 실제 객체가 원격 서버에 있을 때, 이를 대신해 로컬에서 작업을 수행합니다.
    • 예시: 원격 서버의 계산 작업을 프록시를 통해 수행합니다.
    interface Calculator { int add(int a, int b); } class RemoteCalculator implements Calculator { @Override public int add(int a, int b) { System.out.println("Performing remote addition"); return a + b; } } class CalculatorProxy implements Calculator { private RemoteCalculator remoteCalculator; @Override public int add(int a, int b) { if (remoteCalculator == null) { remoteCalculator = new RemoteCalculator(); } return remoteCalculator.add(a, b); } } public class Main { public static void main(String[] args) { Calculator calculator = new CalculatorProxy(); System.out.println("Result: " + calculator.add(10, 20)); // 원격 계산 수행 } }

    4. 캐싱 프록시 (Caching Proxy)

    • 목적: 반복적인 요청에 대해 동일한 결과를 반환할 때, 결과를 캐싱하여 성능을 향상시킵니다.
    • 예시: 자주 조회되는 데이터를 캐싱하여 데이터베이스에 대한 반복적인 쿼리를 줄입니다.
    interface DataFetcher { String fetchData(); } class RealDataFetcher implements DataFetcher { @Override public String fetchData() { System.out.println("Fetching data from the database..."); return "Data from database"; } } class CachingProxyDataFetcher implements DataFetcher { private RealDataFetcher realDataFetcher; private String cachedData; @Override public String fetchData() { if (cachedData == null) { realDataFetcher = new RealDataFetcher(); cachedData = realDataFetcher.fetchData(); } else { System.out.println("Returning cached data"); } return cachedData; } } public class Main { public static void main(String[] args) { DataFetcher dataFetcher = new CachingProxyDataFetcher(); System.out.println(dataFetcher.fetchData()); // 실제 데이터베이스에서 데이터 가져옴 System.out.println(dataFetcher.fetchData()); // 캐시된 데이터 반환 } }

    5. 스마트 프록시 (Smart Proxy)

    • 목적: 객체에 대한 접근을 제어하면서, 객체에 추가적인 기능을 제공합니다.
    • 예시: 객체의 참조 횟수를 관리하는 스마트 프록시를 구현합니다.
    interface Resource { void use(); } class RealResource implements Resource { @Override public void use() { System.out.println("Using resource"); } } class SmartProxyResource implements Resource { private RealResource realResource; private int referenceCount = 0; @Override public void use() { if (realResource == null) { realResource = new RealResource(); } referenceCount++; System.out.println("Resource is being used. Reference count: " + referenceCount); realResource.use(); } public void release() { if (referenceCount > 0) { referenceCount--; System.out.println("Resource released. Reference count: " + referenceCount); if (referenceCount == 0) { realResource = null; System.out.println("Resource is no longer needed and has been deallocated."); } } } } public class Main { public static void main(String[] args) { SmartProxyResource resourceProxy = new SmartProxyResource(); resourceProxy.use(); // 참조 횟수 증가 resourceProxy.use(); // 참조 횟수 증가 resourceProxy.release(); // 참조 횟수 감소 resourceProxy.release(); // 참조 횟수 0이 되어 리소스 해제 } }

    프록시 패턴의 장점

    1. 객체 생성 지연: 가상 프록시를 사용하면, 실제 객체의 생성이 지연되어 메모리 사용량과 성능을 최적화할 수 있습니다.
        • 예시: 큰 이미지 파일을 가상 프록시를 통해 필요할 때만 로드하여 메모리 사용을 줄임.
    1. 접근 제어: 보호 프록시를 통해 객체에 대한 접근을 제어하고, 보안 수준을 높일 수 있습니다.
        • 예시: 보호 프록시를 사용하여, 사용자 권한에 따라 문서의 접근을 제한함.
    1. 추가 기능 제공: 스마트 프록시를 사용하면, 객체에 대한 추가 기능을 제공하거나, 객체의 상태를 관리할 수 있습니다.
        • 예시: 스마트 프록시를 통해 객체의 참조 횟수를 관리하여 리소스를 효율적으로 사용함.
    1. 원격 객체 접근: 원격 프록시를 사용하여, 원격 서버에 있는 객체에 쉽게 접근할 수 있습니다.
        • 예시: 원격 프록시를 통해 원격 서버에서 계산 작업을 수행함.
    1. 성능 향상: 캐싱 프록시를 사용하여 반복적인 요청에 대해 동일한 결과를 반환할 때, 결과를 캐싱하여 성능을 향상시킬 수 있습니다.
        • 예시: 캐싱 프록시를 사용하여 데이터베이스에 대한 반복적인 쿼리를 줄임.
    프록시 패턴을 사용하면 시스템의 유연성을 높이고 성능을 최적화할

    프록시 패턴의 단점

    1. 복잡성 증가: 프록시 객체를 추가하면 시스템의 복잡성이 증가할 수 있으며, 유지보수가 어려워질 수 있습니다.
    1. 성능 오버헤드: 프록시를 통해 모든 요청이 처리되므로, 프록시 객체의 성능이 중요한 경우에는 성능 오버헤드가 발생할 수 있습니다.
    1. 코드 중복: 프록시 객체와 실제 객체 간의 인터페이스가 동일해야 하므로, 일부 코드 중복이 발생할 수 있습니다.
     
     
    Share article
    Contents
    프록시 패턴의 구성 요소프록시 패턴의 종류와 예시프록시 패턴의 장점

    heo-gom

    RSS·Powered by Inblog