프록시 패턴(Proxy Pattern)

wannabeking·2022년 10월 17일
0

디자인 패턴

목록 보기
12/14
post-thumbnail

실행 시간 측정 기능

Service를 구현하는 HelloServiceByeService가 존재한다.

새로운 요구사항으로 두 서비스의 특정 메소드 실행 시간을 측정하는 기능 추가를 부탁받았다.

또한 기존 서비스 코드에는 수정이 없어야하고, 서비스를 호출할 때마다 시간 측정 로직을 추가하면 안된다는 제한사항도 존재했다.

기존 코드에 수정 없이 어떻게 기능을 추가해야할까?
프록시 패턴으로 해결해보자.



프록시 패턴

CORS 문제 해결 등의 이유로 클라이언트의 요청을 서버에 대신 요청하고 응답 받아 전달해주는 프록시 서버처럼, 프록시는 대리인이라는 뜻이다.

따라서 프록시 패턴 또한 가지고 있는 이름처럼 대리인을 두는 패턴이다.

실제 객체를 대신하기 때문에 임의의 기능을 추가할 수 있다.

코드를 살펴보자.


public interface Service {

    void doSomething();
}

무언가 기능을 수행하는 서비스가 존재한다.


public class HelloService implements Service {

    @Override
    public void doSomething() {
        System.out.println("Hello!");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
public class ByeService implements Service {

    @Override
    public void doSomething() {
        System.out.println("Bye~");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}

서비스에는 위와 같은 각각 "Hello!", "Bye~"를 출력하는 간단한 서비스 구현체가 있다.

우리는 프록시를 사용하여 doSomething()의 실행 시간을 체크하는 로직을 추가할 것이다.


public class ServiceProxy implements Service {

    private final Service service;

    public ServiceProxy(Service service) {
        this.service = service;
    }

    @Override
    public void doSomething() {
        long start = System.currentTimeMillis();
        System.out.println("--시간 측정 시작--");
        service.doSomething();
        System.out.println("--시간 측정 완료 : " + (System.currentTimeMillis() - start) + "ms--");
    }
}

ServiceProxyService를 구현 및 구성하여 메소드를 대신 호출하고, 그 전후에 시간 측정 로직을 끼워 넣었다.


public class Main {

    public static void main(String[] args) {
        Service helloService = new HelloService();
        Service byeService = new ByeService();
        Service proxyService = new ServiceProxy(helloService);

        proxyService.doSomething();
        proxyService = new ServiceProxy(byeService);
        proxyService.doSomething();
    }
}

이제 클라이언트는 기존 객체를 사용하는 대신 프록시 객체를 사용하여 시간 측정 로직이 추가된 메소드를 실행한다.

출력 결과는 다음과 같다.


프록시는 어떠한 행동을 추가해주기만 하는게 아니라 주제(Subject)를 대신한다.
따라서 주제로의 접근을 제어하는 기능도 제공한다.

여러 기능을 제공할 수 있는 만큼 용도에 따른 수 많은 변종이 존재하기도 한다.

단점으로는 기존 객체가 존재하는데 프록시 객체가 추가적으로 구현되고 생성되므로 불필요하게 사용하면 오히려 성능적인, 가독성의 측면에서 저하될 수 있다.


모든 소스코드는 여기에서 확인할 수 있다.



profile
내일은 개발왕 😎

0개의 댓글