정의
예를 들어 우리가 시스템 명렁어를 실행하는 객체를 갖고 있을 때 우리가 그 객체를 사용하는 것이라면 괜찮지만, 만약 그 객체를 클라이언트에게 제공하려고 한다면 클라이언트 프로그램이 우리가 원치 않는 파일을 삭제하거나 설정을 변경하는 등의 명령을 내릴 수 있기 때문에 심각한 문제를 초래할 수 있습니다.
프록시 패턴은 클라이언트에게 접근에 대한 컨트롤을 제공하여 위와 같은 문제를 해결합니다.
CommandExecutor 라는 cmd 명령어를 실행하는 메소드를 제공하는 인터페이스를 정의하겠습니다.
CommandExecutor.java
public interface CommandExecutor {
public void runCommand(String cmd) throws Execption;
}
먼저 프록시 패턴을 적용하지 않고 앞서 말씀드린 것처럼 그냥 클라이언트에게 명령에 대한 권한을 전부 넘겨주는 객체를 생성해보겠습니다.
CommandExecutorImpl.java
public class CommandExecutorImpl implements CommandExecutor {
@Override
public void runCommand(String cmd) throws IOException {
// some heavy implementation
Runtime.getRuntime().exec(cmd);
System.out.println("'" + cmd + "'" + "command executed.");
}
}
보시다시피 CommandExecutorImpl 클래스에서는 runCommand()의 파라미터로 받은 cmd 명령어를 그대로 수행하고 있습니다.
이렇게 구현할 경우에는 앞서 말씀드린 바와 같이 원치 않는 파일 삭제나 설정 변경 등에 대한 문제가 발생할 가능성이 높아집니다.
그렇다면 이를 해결하기 위해 프록시 객체를 두어 관리자(Admin) 계정이 아닐 경우에는 rm 이라는 명령어에 대해 수행하지 못하도록 구현해보도록 하겠습니다.
CommandExecutorProxy.java
public class CommandExecutorProxy implements CommandExecutor {
private boolean isAdmin;
private CommandExecutor executor;
public CommandExecutorProxy(String user, String pwd){
if("yuseogi".equals(user) && "correct_pwd".equals(pwd)){
isAdmin = true;
}
executor = new CommandExecutorImpl();
}
@Override void runCommand(String cmd) throws Exception {
if(isAdmin){
executor.runCommadn(cmd);
}else{
if(cmd.trim().startWith("rm"){
throws new Exception("rm command is not allowed for non-admin users.");
}else{
executor.runCommand(cmd);
}
}
}
}
이제 위에서 작성한 예제 코드를 테스트 할 수 있는 코드를 작성해 보겠습니다.
TestProxyPattern.java
public class TestProxyPattern {
public static void main(String[] args) {
CommandExecutor executor = new CommandExecutorProxy("yuserogi", "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' command executed.
Exception Message::rm command is not allowed for non-admin users.
결과에서 보다시피 Admin 계정의 ID와 Password가 틀렸기 때문에 프록시 객체가 rm 명령어에 대한 수행을 거부하였고 그 결과로 Exception을 던지게 됐습니다.
프록시 패턴은 이렇듯 어떤 객체에 대하여 접근할 때에 Wrapper Class를 두어 접근에 대한 통제(Control access)를 위해 사용합니다.