프록시 패턴(Proxy Pattern)

hjkim·2022년 3월 20일
1

프록시 패턴(Proxy Pattern)

프록시(Proxy)는 대리자, 대변인의 의미를 갖고 있다. 즉, 누군가를 대신하여 그 역할을 수행하는 존재이다. 프록시 패턴에서도 동일한 의미를 갖는다. 직접적으로 객체를 참조하는 것이 아니라 프록시에 해당하는 객체를 거쳐 대상 객체에 접근하는 방식을 '프록시 패턴'이라 한다.
이러한 방식으로 접근하면 현재 대상 객체가 메모리에 존재하지 않더라도 기본 정보들을 참조하거나 설정할 수 있고, 실제 객체의 기능이 필요한 시점까지 객체의 생성을 미룰 수 있다.

코드로 살펴보면 아래와 같다.

public interface Image {
    public void display();
}

이미지는 jpg, png, bmp 등 서로 다른 확장자를 가질 수 있다. 이때, 이미지 확장자별로 다르게 처리해야 하는 경우가 발생할 수 있다. 이러한 경우들에 대해 프록시 패턴을 사용하는 예제 코드를 작성해보고자 한다. 우선 jpg, png, bmp 이미지들이 공통적으로 가져야 할 것들을 interface Image로 구현하였다.

public class JPG implements Image {
    private String fileName;

    public JPG(String fileName) {
        this.fileName = fileName;
    }

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

위의 코드는 여러 이미지들 중 jpg 이미지를 처리하도록 하는 코드이다. 여기까지 작성한 후 main 함수에서 Image = new JPG();로 생성해 사용할 수도 있다. 하지만 이렇게 직접적으로 객체를 생성하지 않고 프록시를 통해 생성한다. 아래의 코드는 프록시 객체이다.

public class ProxyImage implements Image {
    private String fileName;
    private Image image;

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

    @Override
    public void display() {
        if (fileName.contains("jpg")) {
            image = new JPG(fileName);
        }
        image.display();
    }
}

프록시 객체에서는 fileName에 jpg가 포함되는 경우 JPG class의 display 메소드를 사용하도록 처리하고 있다.

public class MainClass {
    public static void main(String[] args) {
        Image image1 = new ProxyImage("test1.jpg");

        image1.display();
    }
}

프록시 패턴이 없었다면

Image image1 = new JPG();
Image image2 = new PNG();

와 같이 직접적으로 생성을 해주어야 한다.
하지만 위와 같이 Proxy 객체를 두면 file명에 따른 class를 Proxy 객체에서 알아서 생성해준다.

프록시 패턴 없이 test1.jpg 파일에서 test1.png 파일로 변경되는 경우
Image image1 = new JPG(); 에서 Image image2 = new PNG();로 코드가 바뀌어야 한다.

하지만 proxy 객체를 사용하면 "test1.jpg"에 해당하는 fileName 매개변수만 수정하면 된다. 실제로 JPG 객체를 사용하는지, PNG 객체를 사용하는지 상관하지 않고 test1.jpg라는 이미지를 처리한다는 관심사에만 집중할 수 있게 해준다.


프록시 패턴의 장단점

장점

  1. 전처리 및 후처리에 용이하다.
  2. 실제 객체의 메소드들을 숨기고 interface를 통해 노출시키고 싶은 부분에 한하여 노출시킬 수 있다. client의 조건에 맞는 부분들만 노출시킬 수 있다.
  3. 클라이언트에서의 사용과 기본 객체 사이의 관계를 프록시 객체를 통해 넣어주므로 클라이언트와 기본 객체에 많은 변경이 발생하지 않는다.
  4. 객체의 생성을 필요한 시점까지 미룰 수 있다. 메모리를 많이 잡아먹는 객체를 끝끝내 사용하지 않을 수도 있다. 따라서 해당 객체의 생성은 필요한 시점까지 미룰수록 좋은데, 프록시 패턴에서 이를 가능하게 해준다.

단점

  1. 코드가 복잡해진다. 만들어야 하는 객체의 수가 많다.
  2. proxy를 거치다보니 속도가 지연된다. 스레드 생성, 동기화가 구현되어야 하는 경우 더 지연된다.

[참조] https://velog.io/@newtownboy/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-%ED%94%84%EB%A1%9D%EC%8B%9C%ED%8C%A8%ED%84%B4Proxy-Pattern
[참조] https://coding-factory.tistory.com/711
[참조] https://min94programming.tistory.com/30
[참조] https://dailyheumsi.tistory.com/201
[참조] https://www.geeksforgeeks.org/lazy-loading-design-pattern
[참조] https://refactoring.guru/design-patterns/proxy

profile
피드백은 언제나 환영입니다! :)

0개의 댓글