프록시 패턴

2020-04-01

프록시패턴(Proxy Pattern)

Gof에 따르면 프록시 패턴의 목적은 다른 오브젝트에 접근해서 컨트롤 하기 위한 대리인을 제공해 주는 것 입니다.

클래스에 관한 기능에 대한 액세스를 제어하려는 경우 프록시 디자인 패턴이 사용됩니다.

시스템을 동작시키는 명령어 클래스가 있다고 가정해봅시다. 프로그램을 클라이언트 프로그램에게 제공하려면 클라이언트 프로그램이 일부 시스템 파일을 삭제하거나 원치 않는 설정을 변경하는 명령을 내릴 수 있기 때문에 심각한 문제가 발생할 수 있습니다.

메인 클래스

CommandExecutor.java

public interface CommandExecutor {
     void runCommand(String cmd) throws Exception;
}

CommandExcutorImpl.java

public class CommandExecutorImpl implements CommandExecutor {

    @Override
    public void runCommand(String cmd) throws IOException {
        Runtime.getRuntime().exec(cmd);
        System.out.println("'" + cmd + "' 명령어가 실행됨.");
    }
}

프록시 클래스

admin 유저와 일반 user 일 때 사용할 수 있는 명령어를 제어할 것입니다.

CommandExecutorProxy.java

public class CommandExecutorProxy implements CommandExecutor {

    private boolean isAdmin;
    private CommandExecutor executor;

    public CommandExecutorProxy(String user, String pwd){
        if("donghyeon".equals(user) && "daeakin@".equals(pwd)) isAdmin=true;
        executor = new CommandExecutorImpl();
    }

    @Override
    public void runCommand(String cmd) throws Exception {
        if(isAdmin){
            executor.runCommand(cmd);
        }else{
            if(cmd.trim().startsWith("rm")){
                throw new Exception("관리자가 아니면 rm 명령어를 사용할 수 없습니다.");
            }else{
                executor.runCommand(cmd);
            }
        }
    }

}

테스트

ProxyPatternTest.java

public class ProxyPatternTest {

    public static void main(String[] args){
        //관리자가 아님
        CommandExecutor executor = new CommandExecutorProxy("Pankaj", "wrong_pwd");
        try {
            executor.runCommand("ls -ltr");
            executor.runCommand(" rm -rf abc.pdf");
        } catch (Exception e) {
            System.out.println("Exception Message::"+e.getMessage());
        }
    }
}

결과

'ls -ltr' 명령어가 실행됨.
Exception Message::관리자가 아니면 rm 명령어를 사용할 수 없습니다.

프록시 패턴 예제 다이어그램

자바에서 사용사례

  • Spring AOP
  • JPA