Proxy Pattern

이한수·2022년 7월 2일
0

디자인 패턴

목록 보기
5/5
post-thumbnail

Proxy Pattern

사용하고자 하는 객체에 직접 접근하는 것이 아닌,
대리자를 통하여 참조하는 것을 의미 한다.

주로 , 접근제어의 목적으로 사용 된다.


사진 : 위키백과

//인터페이스
public interface Subject{
	void doAction();
}


//구체클래스
@Slf4j
public class RealSubject implements Subject{
		
        @Override
   		public void doAction(){
      		log.info("Concrete doAction 실행");  		
        }
}

//Client
public class Client{
	private Subject subject;
    
    public Client(Subject subject){
    	this.subject= subject;
    }
    
}

해당 코드를 클라이언트에서 호출한다고 해보자.

//생성 및 호출
RealSubject sub1 = new RealSubject();
Client client = new Client(sub1);

client.subject.doAction();


//출력 결과
Concrete doAction 실행

코드를 수정하거나 추가하고 싶을 경우 ,
RealSubject의 doAction 메소드를 수정하면 된다.

여기서 만일 사용자에 따라 접근에 대한 권한을 부여하고 싶다고 가정해보자.
(Admin , NomarlUser)

Admin만 핵심로직을 실행할 수 있을 경우 아래처럼 바꿀 수 있다.

//인터페이스
public interface Subject{
	void doAction(String grade);
}

@Slf4j
public class RealSubject implements Subject{
		
        @Override
   		public void doAction(String grade){
        	
            if(grade.equals("Admin"){
	      		log.info("Concrete doAction 실행");  	
            }
        }
}


변경이 필요할 경우 , 직접 클래스의 내용을 변경해야 한다.(심지어 현재의 경우 인터페이스까지 수정을 했다)

사용자에 대한 접근의 권한을 파악하는 로직도 함께 작성되어 있다.

지금이야 간단하지만 , 실제의 접근 권한을 확인하는 로직은 훨씬 복잡할 것이다.
그런 방대한 양의 코드가 한곳에 몰려 있으면 , 가독성 또한 좋지 못할 것이다.

또 접근 권한과 핵심 로직 둘 중에 하나의 기능에서라도 수정이나 확장이 발생을 고려하게 된다면 , 매번 해당 클래스를 수정해야 한다.

그럼 프록시를 도입해보자.

//인터페이스
public interface Subject{
	void doAction();
}

//프록시
public class ProxySubject implements Subject{
	
    private Subject subject;
    private String grade;
    public ProxySubject(Subject subject , String grade){
    	this.subject = subject;
    	this.grade = grade;
    }
    
    @Override
    public void doAction(){
    	 if(grade.equals("Admin"){
    		subject.doAction();
          }  
    }
}

//구체 
@Slf4j
public class RealSubject implements Subject{
		
        @Override
   		public void doAction(){       
	      		log.info("Concrete doAction 실행");  	
         
        }
}

내부에 구체클래스를 호출할 수 있게 참조하고 있다.
또한, 인터페이스와 구체클래스는 수정없이 그대로 두고
접근 권한 확인로직을 추가하였다.

프록시를 도입하여 책임을 분리 시킴으로써 , 훨씬 확장과 수정에 유리하게 바꾸었다.

//생성및 호출
RealSubject sub1 = new RealSubject();
ProxySubject sub2 = new ProxySubject(sub1);
Client client = new Client(sub2);
client.subject.doAction("Admin");


//결과

단점

-사전 작업을 위한 빈번한 객체 생성이 필요할 경우 성능이 저하될 수 있다.
-동기성 문제등의 기능을 고려하여 작업이 필요할 경우 성능이 저하될 수 있다.

프록시 패턴은 사용목적에 따라 3가지로 분류할 수 있다.

종류

가상 프록시

필요로 하는 시점까지 객체의 생성을 연기 하고 , 해당 객체가 생성된 것처럼 동작하도록 만들고 싶을때 사용하는 패턴이라고 한다.

프록시에서 간단한 기능들은 처리하도록 한다.
그리고 많은 작업량을 요구하는 리소스의 경우 , 본 객체를 사용하도록 구현할 때 이용한다.

원격 프록시

원격객체에 대한 대변자 역할을 하는 객체 서로다른 주소 공간에 있는 객체에 대해 마치 같은 주소 공간에 있는 것처럼 동작하게 만드는 패턴이라고 한다.
Google Docs를 예시로 들 수 있다.
브라우저는 브라우저대로 필요한 자원을 로컬에 가지고 있고 또다른 자원은 Google 서버에 있는 형태이다.

보호 프록시

위의 예시처럼 구체 클래스에 대한 접근을 제어하기 위한 경우 사용하는 방식을 의미한다.

참고 :
https://ko.wikipedia.org/wiki/%ED%94%84%EB%A1%9D%EC%8B%9C_%ED%8C%A8%ED%84%B4

https://coding-factory.tistory.com/711

https://daru-daru.tistory.com/54?category=788166

https://velog.io/@newtownboy/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-%ED%94%84%EB%A1%9D%EC%8B%9C%ED%8C%A8%ED%84%B4Proxy-Pattern

profile
성실하게

0개의 댓글