관리 메뉴

IT.FARMER

프록시 패턴(proxy) 본문

소프트웨어공학/Design Pattern

프록시 패턴(proxy)

아이티.파머 2023. 1. 5. 17:20
반응형

프록시 패턴(proxy)

프록시패턴이란 ?

특정 객체에 대한 접근을 제어하거나 기능을 추가 할 수 있는 패턴이다.

  • 초기화지연, 접근제어, 로깅, 캐싱 등에서 다양하게 응용하여 사용 할 수 있다.

Proxy Pattern 은 우리가 알고있는것 처럼 구조에 대한 패턴중 하나이다. 기본 기능을 가지고 있는 어떠한 Subject<> 가 있다고 하면 우린 이것에 직접 손을 대지 않고 Proxy class 통해 앞서 이야기한 초기화지연, 접근제어, 로깅등등의 기능을 구현한다.

그림으로 보면 다음과 같다.

클라이언트에서는 Subject 인터페이스를 참조하고 실제 구현은 RealSubject 클레스에 구현되어 있다. RealSubject 에 구현된 기능을 사용할때 접근제어, 로깅, 캐싱들을 이용하고자 할경우 Proxy Class 생성을하여 RealSubject를 참조하도록 한다.

예시 )

게임시작시 오퍼레이션의 구동시간을 알고자할경우

기본코드

public class Client {

    public static void main(String[] args) {
        GameServer gameServer = new GameServer();
        gameServer.startGame();
    }

}

public class GameServer {

    public void startGame() {
        System.out.println("이 자리에 오션 여러분을 진심으로 환영합니다.");
    }
}

실행결과
-----
이 자리에 오션 여러분을 진심으로 환영합니다.

메인 클레스에서 앞뒤에 시작시간과 종료시간을 넣어 계산하면 된다.

프록시 패턴을배워보기로 했으니, 기존코드를 손대지 않고 오퍼레이션의 구동시간을 구해 보도록 하자.

기존코를 수정하지 않고 상속하여 Proxy 구현


public class Client {

    public static void main(String[] args) {
        GameServer gameServer = new GameServerProxy();
        gameServer.startGame();
    }

}

public class GameServer {

    public void startGame() {
        System.out.println("이 자리에 오션 여러분을 진심으로 환영합니다.");
    }
}

public class GameServerProxy extends GameServer{

     public void startGame () {
         long begin = System.currentTimeMillis();
         super.startGame();
         System.out.println("걸린 시간 : " + (System.currentTimeMillis()-begin));
     }
}

결과

이 자리에 오션 여러분을 진심으로 환영합니다.
걸린 시간 : 1

너무 빠르게 지나가다보니 걸린시간이 1마이크로초가 나온것이지만 우리가 목표로 했던 프록시패턴을 구현했다.

또다른 방법으로 Interface를 활용해보자


public interface GameService {

    void startGame();
}

public class DefaultGameService implements GameService {

    @Override
    public void startGame() {
        System.out.println("이 자리에 오션 여러분을 진심으로 환영합니다.");

    }
}

public class GameServiceProxy implements GameService {

    private GameService gameService;

    public GameServiceProxy(GameService gameService) {
        this.gameService = gameService;
    }

    @Override
    public void startGame() {
        long begin = System.currentTimeMillis();
        gameService.startGame();
        System.out.println("걸린 시간 : " + (System.currentTimeMillis()-begin));
    }
}

public class Client {
    public static void main(String[] args) {
        System.out.println("--------------------proxy 없음 ------------------");
        GameService gameService = new DefaultGameService();
        gameService.startGame();

        System.out.println("--------------------proxy 사용 ------------------");

        gameService = new GameServiceProxy(new DefaultGameService());
        gameService.startGame();
    }
}

결과

--------------------proxy 없음 ------------------
이 자리에 오션 여러분을 진심으로 환영합니다.
--------------------proxy 사용 ------------------
이 자리에 오션 여러분을 진심으로 환영합니다.
걸린 시간 : 1

인터페이스를 사용하여 프록시패턴을 구현해 보았다.

인터페이스를 상속하여 구현하고 Proxy 객체에서는 field로 인터페이스를 가지고 있는다.

 

이처럼 RealSubject 를 수정하지 않고 대리자 처럼 Proxy Class를 만들어 기능을 구현 할 수있다. 경우에 따라 Proxy Class 에서 RealSubject를 생성자로 주입받지 않고 laze initialization 할 수도 있다. 또는 RealSubject의 기능을 사용하기전에 권한을 체크하거나 로깅을 남기는 기능을 할 수도있다.

연관키워드로 Spring AOP, Dinamic Proxy, JDK Proxy 을 검색해보면 좋을것 같다.

참고

https://www.youtube.com/watch?v=tes_ekyB6U8

반응형