디자인패턴 - 프록시 패턴

JeongHoHyun·2025년 3월 10일

Java

목록 보기
20/23

프록시 패턴(Proxy Pattern)

프록시 패턴은 어떤 객체에대한 접근을 제어하기 위해 대리자(Proxy) 객체를 사용하는 디자인 패턴이다.
즉, 클라이언트가 실제 객체를 직접 접근하지않고 프록시(대리인)를 통해 접근하도록 만든다.

핵심 개념

  • 실제 객체(Real Subject) 앞에 대리 객체(Proxy)를 두어 요청을 중간에서 가로채거나 추가적인 기능을 수행.
  • 클라이언트는 프록시를 통해서만 객체에 접근할 수 있다.

주요 목적

  • 접근 제어(Access Control) : 보안, 인증 등의 추가 작업 수행 가능.
  • 성능 향상(Cache, Lazy Loading) : 필요할 때만 실체 객체를 생성.
  • 로깅(Logging) : 요청을 중간에서 감시하고 기록.

구조

  1. Subject (인터페이스 또는 추상클래스)

    • 실제 객체(Real Subject)와 프록시 객체(Proxy)의 공통 인터페이스를 정의.
  2. Real Subject (실제 객체)

    • 실제 동작을 수행하는 클래스
  3. Proxy(프록시 객체)

    • Real Subject와 동일한 인터페이스를 구현하고, 클라이언트의 요청을 실제 객체로 전달하면서 부가적인 기능을 수행.

예제 (Java)

Subject 인터페이스

// 공통 인터페이스
public interface Image {
    void display();
}

RealSubject (실제 객체)

// 실제 이미지 클래스 (이미지를 로드하고 출력)
public class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadImage();  // 생성 시 이미지 로드 (비싼 작업)
    }

    private void loadImage() {
        System.out.println(filename + " 이미지를 로딩 중...");
    }

    @Override
    public void display() {
        System.out.println(filename + " 이미지를 화면에 표시합니다.");
    }
}

Proxy (대리 객체)

// 프록시 클래스 (실제 이미지의 로딩을 지연시키는 역할)
public class ProxyImage implements Image {
    private String filename;
    private RealImage realImage; // 실제 객체 참조

    public ProxyImage(String filename) {
        this.filename = filename;
    }

    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename);  // 실제 객체를 필요할 때만 생성 (Lazy Loading)
        }
        realImage.display();
    }
}

클라이언트 코드

public class ProxyPatternExample {
    public static void main(String[] args) {
        Image image1 = new ProxyImage("photo1.jpg");
        Image image2 = new ProxyImage("photo2.jpg");

        // 실제 이미지를 로드하지 않고 프록시만 생성됨
        System.out.println("\n=== 첫 번째 이미지 호출 ===");
        image1.display();  // 여기서만 RealImage 생성 및 로딩

        System.out.println("\n=== 첫 번째 이미지 다시 호출 ===");
        image1.display();  // 이미 로드된 이미지 사용 (캐싱 효과)

        System.out.println("\n=== 두 번째 이미지 호출 ===");
        image2.display();  // 두 번째 이미지 로딩
    }
}

주요 유형

가상 프록시 (Virtual Proxy)

  • 비싼(무거운) 객체의 생성을 지연 (Lazy Loading).
  • 위의 ProxyImage예제가 대표적

보호 프록시 (Protection Proxy)

  • 보안 및 접근 제어가 필요한 경우.
  • ex) 관리자 권한이 있는 사용자만 특정 기능을 사용하도록 제한.
public class ProtectionProxy implements Image {
    private RealImage realImage;
    private String filename;
    private boolean hasPermission;

    public ProtectionProxy(String filename, boolean hasPermission) {
        this.filename = filename;
        this.hasPermission = hasPermission;
    }

    @Override
    public void display() {
        if (!hasPermission) {
            System.out.println("접근이 거부되었습니다.");
            return;
        }
        if (realImage == null) {
            realImage = new RealImage(filename);
        }
        realImage.display();
    }
}

캐싱 프록시 (Caching Proxy)

  • 같은 요청이 반복될 경우 캐싱하여 성능을 향상.
  • 네트워크 요청, 데이터베이스 조회 등에서 활용됨.
public class CachedImageProxy implements Image {
    private String filename;
    private RealImage realImage;
    private boolean isLoaded = false;

    public CachedImageProxy(String filename) {
        this.filename = filename;
    }

    @Override
    public void display() {
        if (!isLoaded) {
            realImage = new RealImage(filename);
            isLoaded = true;
        }
        realImage.display();
    }
}

원격 프록시 (Remote Proxy)

  • 네트워크를 통해 원격 객체를 제어하는 경우.
  • RMI(Remote Method Invocation) 같은 분산 시스템에서 활용됨.
// 원격 서버에서 동작하는 객체를 프록시로 대체
public interface RemoteService extends java.rmi.Remote {
    String getData() throws java.rmi.RemoteException;
}

프록시 패턴의 장점과 단점

✅ 장점

  • 접근 제어 기능 제공
    • 객체에 대한 접근을 제어하고 보안 정책을 적용할 수 있음.
  • 성능 향상(Lazy Loading & Caching)
    • 필요할 때만 객체를 생성하여 불필요한 리소스 낭비를 방지.
  • 로깅 및 감시 기능 추가 가능
    • 객체의 동작을 감시하고 로깅할 수 있어 디버깅과 성능 분석이 쉬움.

❌ 단점

  • 복잡성이 증가
    • 객체마다 추가적인 프록시 클래스가 필요하여 코드가 길어질 수 있음.
  • 응답 속도 지연
    • 프록시를 거쳐야 하므로 실행 속도가 느려질 가능성이 있음.
profile
Java Back-End 2022.11.01 💻~ing

0개의 댓글