JAVA/JAVA Design Pattern

JAVA 접근 제어를 위한 프록시(Proxy) 패턴

임베디드 친구 2024. 12. 26. 08:49
반응형

프록시(Proxy) 패턴은 객체의 접근을 제어하거나 대리 역할을 수행하기 위해 사용되는 디자인 패턴입니다. 프록시 객체를 통해 실제 객체의 접근을 간접적으로 제어할 수 있습니다. 이번 포스팅에서는 프록시 패턴의 개념, 종류, 클래스 다이어그램, 사용 사례, 그리고 예제 코드를 소개하겠습니다.

1. 프록시(Proxy) 패턴이란?

프록시 패턴은 특정 객체에 대한 대리자(Proxy) 를 제공하여 접근을 제어하는 패턴입니다.

  • 프록시 객체는 실제 객체와 같은 인터페이스를 제공하며, 대리하여 요청을 처리하거나 전달합니다.
  • 사용자는 프록시 객체를 통해 실제 객체에 접근하며, 직접 접근하지 않습니다.

프록시 패턴은 다음과 같은 목적으로 사용됩니다:

  • 접근 제어
  • 리소스의 지연 초기화 (Lazy Loading)
  • 원격 접근 (Remote Access)
  • 접근 보호

2. 프록시 패턴의 주요 종류

프록시 패턴에는 몇 가지 유형이 존재합니다:

유형 설명
가상 프록시 리소스가 무겁거나 초기화가 오래 걸릴 때 실제 객체 대신 프록시를 사용합니다.
원격 프록시 네트워크를 통해 원격 객체에 접근할 때 프록시를 사용합니다.
보호 프록시 접근 권한을 확인하고 제한하기 위해 프록시를 사용합니다.

3. 클래스 다이어그램

       +------------+
       |   Client   |
       +------------+
              |
              v
       +------------+
       |   Subject  |<----------------+
       +------------+                 |
              ^                       |
              |                       |
       +------------+          +----------------+
       |   Proxy    |          |   RealSubject  |
       +------------+          +----------------+
              |                       |
              | (Access Control)      | (Actual Logic)
              v                       v
      (Virtual Loading, Access Control, etc.)
  • Subject: 프록시와 실제 객체가 구현할 공통 인터페이스입니다.
  • Proxy: 대리자 역할을 수행하며 접근 제어를 수행합니다.
  • RealSubject: 실제 작업을 수행하는 객체입니다.
  • Client: 프록시 객체를 통해 간접적으로 실제 객체에 접근합니다.

4. 프록시 패턴 사용 사례

프록시 패턴은 다음과 같은 상황에서 사용됩니다:

  1. 지연 초기화 (Lazy Loading): 무거운 객체의 생성을 지연시키고 필요할 때 초기화합니다.
  2. 원격 접근: 네트워크를 통해 원격 객체에 접근합니다.
  3. 보호 기능: 권한 검사 및 제한을 적용합니다.
  4. 캐싱: 객체에 대한 캐싱 기능을 제공하여 성능을 개선합니다.

5. 예제 코드

아래는 프록시 패턴의 간단한 예제 코드입니다. 가상 프록시를 통해 리소스가 무거운 객체의 생성을 지연시키는 예제입니다.

5.1. Subject 인터페이스

interface Image {
    void display();
}

5.2. RealSubject - 실제 객체

class RealImage implements Image {
    private String fileName;

    public RealImage(String fileName) {
        this.fileName = fileName;
        loadFromDisk();
    }

    private void loadFromDisk() {
        System.out.println("Loading " + fileName);
    }

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

5.3. Proxy - 대리 객체

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();
    }
}

5.4. Client - 프록시 객체 사용

public class ProxyPatternDemo {
    public static void main(String[] args) {
        Image image1 = new ProxyImage("test_image1.jpg");
        Image image2 = new ProxyImage("test_image2.jpg");

        // 첫 번째 호출: RealImage 객체가 생성됨
        System.out.println("Calling display on image1");
        image1.display();

        // 두 번째 호출: 이미 생성된 RealImage 객체를 재사용
        System.out.println("Calling display on image1 again");
        image1.display();

        // 새로운 이미지 호출: 새로운 RealImage 객체 생성
        System.out.println("Calling display on image2");
        image2.display();
    }
}

5.5. 실행 결과

Calling display on image1
Loading test_image1.jpg
Displaying test_image1.jpg
Calling display on image1 again
Displaying test_image1.jpg
Calling display on image2
Loading test_image2.jpg
Displaying test_image2.jpg

6. 결론

프록시 패턴은 객체의 접근 제어, 리소스 지연 초기화, 접근 보호 등 다양한 목적으로 활용할 수 있는 강력한 패턴입니다. 특히 리소스 사용이 무거운 객체를 다룰 때 가상 프록시를 사용하면 효율적으로 시스템 성능을 최적화할 수 있습니다.

프록시 패턴을 적절히 사용하면 코드의 구조를 개선하고 리소스를 효율적으로 관리할 수 있습니다. 다양한 유형의 프록시를 이해하고 프로젝트에 적용해보세요!

반응형