본문 바로가기
[이직 면접] 질의 응답

[Web 개발 기본] Proxy Pattern에 대해서 설명 하세요.

by 막개발자 2020. 12. 6.

# 질의 응답 상황

[면접관]

지원자님 Web 개발을 주로 사용하셨는데 Proxy Pattern에 대해서 간략하게 설명해주세요.

 

[막개발자] 

네 Proxy Pattern은 실제 객체에 대한 호출을 대리자 객체를 통해 간접적으로 실행하는 디자인 패턴입니다.

클라이언트는 실제 객체와 대리 객체를 구분할 수 없으며, 대리 객체는 호출 전에 추가적인 작업을 처리할 수 있습니다.
중요한 점은 흐름을 제어할 뿐, 결과값을 변경하지 않는다는 점입니다.

 

 

# 상세 설명

 

프록시 패턴(Proxy Pattern)은 객체에 대한 접근을 제어할 수 있도록 도와주는 구조적 디자인 패턴입니다. 이 패턴에서는 실제 객체에 대한 접근을 제어하는 "대리자" 객체를 사용하여 원래 객체의 동작을 대체하거나 추가적인 동작을 수행합니다. 프록시 패턴을 사용하면 여러 상황에서 객체의 접근을 효율적으로 관리할 수 있습니다.

프록시 패턴의 목적

프록시 패턴은 실제 객체에 대한 간접 접근을 제공하며, 다음과 같은 주요 목적을 가지고 있습니다:

  • 접근 제어: 프록시는 실제 객체에 대한 접근을 제어하여 보안, 권한 검사를 할 수 있습니다.
  • 지연 로딩 (Lazy Loading): 실제 객체가 필요할 때까지 초기화하지 않고, 실제 객체가 요청될 때까지 로딩을 지연시킬 수 있습니다.
  • 성능 최적화: 실제 객체에 대한 접근을 최적화하거나, 네트워크 통신, 데이터베이스 쿼리 등을 캐시하여 성능을 향상시킬 수 있습니다.
  • 원격 접근: 원격 서버에 존재하는 객체에 접근할 때 네트워크 지연을 처리하거나, 원격 객체의 요청을 대체할 수 있습니다.
  • 로깅 및 트랜잭션 처리: 객체에 대한 호출을 감시하고, 로그를 기록하거나 트랜잭션 처리를 추가할 수 있습니다.

프록시 패턴의 구성 요소

프록시 패턴은 일반적으로 다음의 세 가지 주요 구성 요소로 이루어집니다:

  1. Subject: 실제 객체가 구현해야 할 인터페이스를 정의합니다. 프록시 객체와 실제 객체는 이 인터페이스를 구현해야 합니다.
  2. RealSubject: 실제 작업을 수행하는 객체입니다. 이 객체는 Subject 인터페이스를 구현하며, 실제 비즈니스 로직을 처리합니다.
  3. Proxy: Subject 인터페이스를 구현하며, RealSubject 객체에 대한 접근을 제어하는 대리자 역할을 합니다. 이 객체는 실제 객체와 동일한 메서드를 제공하되, 실제 객체의 메서드를 호출하기 전에 추가적인 로직을 수행할 수 있습니다.

프록시 패턴의 종류

프록시 패턴은 목적에 따라 여러 가지 형태로 나눌 수 있습니다. 대표적으로는 다음과 같은 종류가 있습니다:

  • 가상 프록시 (Virtual Proxy): 실제 객체를 지연 로딩할 때 사용됩니다. 객체가 실제로 필요할 때까지 초기화하지 않고, 요청이 있을 때 객체를 생성합니다. 예시: 이미지 뷰어에서 실제 이미지 객체를 지연 로딩하여 메모리 사용을 최적화합니다.
  • 보호 프록시 (Protection Proxy): 객체에 대한 접근을 제어하고 보호하는 역할을 합니다. 특정 사용자나 조건에 따라 객체에 대한 접근을 제한할 수 있습니다. 예시: 파일 접근을 보호하기 위해 파일 객체에 접근할 때 권한을 검사하는 방식입니다.
  • 원격 프록시 (Remote Proxy): 원격 서버에 위치한 객체에 대한 접근을 관리합니다. 네트워크 상에서 객체에 접근하는 데 발생하는 문제를 처리합니다. 예시: 클라이언트가 서버에 있는 객체에 접근할 때, 원격 프록시가 클라이언트와 서버 간의 통신을 처리합니다.
  • 스마트 프록시 (Smart Proxy): 객체에 대한 접근 시 추가적인 작업을 수행하는 프록시입니다. 예를 들어, 메모리 관리, 객체의 상태 추적, 로깅 등을 처리합니다. 예시: 메모리 사용량을 모니터링하거나, 객체에 대한 호출 횟수를 추적하는 등의 기능을 수행합니다.

프록시 패턴의 예시

1. 가상 프록시 예시

// 실제 객체
class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadImage();
    }

    private void loadImage() {
        System.out.println("Loading image: " + filename);
    }

    @Override
    public void display() {
        System.out.println("Displaying image: " + filename);
    }
}

// 프록시 객체
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);
        }
        realImage.display();
    }
}

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

// 사용 예시
public class ProxyPatternExample {
    public static void main(String[] args) {
        Image image1 = new ProxyImage("image1.jpg");
        image1.display();  // 실제로 이미지를 로드하고 표시함
        image1.display();  // 이미 로드된 이미지를 다시 표시함
    }
}

2. 보호 프록시 예시

// 실제 객체
class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject: Handling request");
    }
}

// 프록시 객체
class Proxy implements Subject {
    private RealSubject realSubject;

    public Proxy() {
        this.realSubject = new RealSubject();
    }

    @Override
    public void request() {
        if (hasPermission()) {
            realSubject.request();
        } else {
            System.out.println("Proxy: Access denied");
        }
    }

    private boolean hasPermission() {
        // 권한 검사 로직
        return false;  // 예시로 접근 권한을 거부
    }
}

// 인터페이스
interface Subject {
    void request();
}

// 사용 예시
public class ProxyPatternExample {
    public static void main(String[] args) {
        Subject subject = new Proxy();
        subject.request();  // 권한이 없으므로 요청이 거부됨
    }
}

프록시 패턴의 장점

  • 유연성: 실제 객체를 호출하는 대신 프록시를 통해 다양한 제어가 가능하므로 유연하게 동작을 변경할 수 있습니다.
  • 성능 최적화: 지연 로딩이나 캐싱을 통해 성능을 최적화할 수 있습니다.
  • 보안 및 권한 관리: 객체에 대한 접근 제어를 쉽게 구현할 수 있습니다.
  • 기타 부가 기능: 로깅, 트랜잭션, 인증 등의 부가 기능을 추가할 수 있습니다.

프록시 패턴의 단점

  • 복잡성 증가: 프록시 객체를 추가함으로써 시스템의 복잡도가 증가할 수 있습니다.
  • 성능 오버헤드: 프록시를 통한 호출이 원래 객체를 직접 호출하는 것보다 느릴 수 있습니다. 특히 추가적인 로직이 포함된 경우 성능에 영향을 줄 수 있습니다.

프록시 패턴은 객체의 접근을 제어하고 관리할 수 있는 유용한 디자인 패턴으로, 다양한 상황에서 사용될 수 있습니다.