프록시 패턴
Last updated
Last updated
특정 객체로의 접근을 제어하는 대리인 역할을 하는 객체를 제공하는 디자인 패턴이다.
클라이언트가 실제 객체의 메서드를 호출했을 때 프록시 객체가 해당 호출 중간에 가로채 필요한 로직을 수행할 수 있다.
생성하기 어려운 객체나 보안이 중요한 객체 등에 대해 접근을 제어하는 대리인 객체를 만들어 사용할 수 있다.
원격(remote) 프록시를 사용해 원격 객체로의 접근을 제어할 수 있다. Java의 RMI가 이 방식에 해당된다.
가상(virtual) 프록시를 사용해 생성하기 힘든 자원으로의 접근을 제어할 수 있다.
생성하는 데에 비용이 많이 드는 객체를 미리 만들어두지 않고 정말 필요할 때 프록시 내부에서 생성하도록 한다.
보호(protection) 프록시를 사용해 접근 권한이 필요한 자원으로의 접근을 제어할 수 있다.
이외에도 방화벽 프록시, 캐싱 프록시, 동기화 프록시 등 다양한 프록시 방법이 존재한다.
실제 클래스와 프록시 클래스는 같은 인터페이스를 구현하여 실제 객체가 들어갈 자리에 프록시 객체를 넣을 수 있도록 한다.
프록시 클래스에는 실제 객체의 참조를 가지며 필요할 때 해당 객체를 사용할 수 있다.
언뜻 보면 특정 클래스를 감싸고 해당 클래스의 인터페이스를 구현한다는 점에서 데코레이터와 비슷할 수 있지만 데코레이터는 클래스에 새로운 행동을 추가하는 용도로 쓰이고 프록시는 클래스의 접근을 제어하는 용도로 쓰인다는 점에서 차이가 있다.
보호 프록시는 클라이언트 역할에 따라 객체에 있는 특정 메서드로의 접근을 제어한다. 따라서 클라이언트에게 인터페이스의 일부분만 제공하는 형태이므로 어댑터 패턴과 유사하다.
장점
클라이언트는 실제 객체를 사용하는지 프록시 객체를 사용하는지 신경쓰지 않아도 된다.
실제 객체가 준비되지 않은 상태에서도 객체를 사용할 수 있는 것 처럼 다뤄질 수 있다.
단점
새로운 클래스를 도입해야 하므로 코드가 복잡해질 수 있다.
부가적인 코드(ex. 초기화가 오래걸리는 객체 생성 등)에 의해 서비스의 응답이 느려질 수 있다.
자바에서는 동적 프록시 기능을 제공한다. 프록시의 메서드가 호출되었을 때 할 일을 지정해주는 핸들러를 만들면 프록시 클래스가 실행 중에 생성되도록 할 수 있다.
InvocationHandler 인터페이스를 구현한 클래스에 invoke 메서드를 작성하고, 자바에서 제공되는 newProxyInstance 메서드를 통해 Proxy 객체를 생성해 사용할 수 있다. Proxy 객체는 메서드 호출을 받으면 항상 InvocationHandler에 작업을 위임하게 된다.