Proxy(프록시)

정명진·2022년 5월 31일
1

프록시란?

프록시란 요청자와 요청을 받는자 사이에 존재하는 중간 대리인을 뜻하는 말이다.

만약 현업 부서에서 원본 코드를 수정하지 않고 로그를 기록하는 기능을 추가해 달라고 하는 상황이라고 하자.
이 문제를 어떻게 해결 할 수 있을까? 원본을 수정하지 않고 원본과 같은 인터페이스를 갖게하여(client가 대리인에게 신청하는지 server에 신청하는지 모르게 하기 위해) 로그 기능을 추가하면 되지 않을까? 이런 경우에 사용하는 것이 바로 Proxy다.

이러한 구조를 갖게 설계하면 된다. 즉 client가 server에 직접 요청하는게 아닌 대리인 Proxy에게 요청하여 간접 호출이 발생하게끔 하는 것 이다.

이렇게 직접 호출 대신 간접 호출을 하게 되면 여러가지 일을 추가적으로 할 수 있다.

ex:

  • 교수님이 사전답사를 하고 오라고 시켰다.
  • 하지만 당신은 그곳을 가본적이 있다. 그러면 답사를 가지 않고 문제를 해결 할 수 있다.(접근 제어, 캐싱)
  • 교수님이 사전답사를 시켰다. 하지만 당신은 시간이 없다. 동기나 후배, 지인에게 요청을 하여 해결 할 수 있다. 중요한 점은 교수님은 당신에게 요청했기 때문에 그 이후 과정은 모른다는 것이다. 즉 교수님은 답사 결과만 받으면 된다.(Proxy Chain)

이렇게 설명을 듣고 보면 아무 객체나 프록시가 될 수 있는 것 같이 들린다. 하지만 객체에서 프록시가 되려면 client는 server에게 요청을 한 것인지, 프록시에게 요청을 했는지 몰라야 한다. 즉 앞에서도 말했듯이 server와 proxy는 같은 인터페이스를 가져야 한다. 그리고 server 객체를 proxy 객체로 변경해도 client는 기존 코드를 변경하지 않고 동작할 수 있어야 한다. 즉 client는 같은 인터페이스에만 의존하게 되기 때문에 DI(Spring 핵심 기능!!)를 통해 대체 가능하다.

프록시의 주요 기능은?

프로시의 주요 기능은 접근 제어, 부가 기능 추가 이렇게 핵심적인 2가지 기능이 있다.

접근 제어

  • 권한에 따른 접근 차단
  • Caching
  • Lazy Loading

부가 기능 추가

  • 원래 서버 기능에 새로운 기능을 추가하여 제공
  • 요청 값이나, 응답 결과를 변형한다던지..
  • 로그를 남긴다던지..
public interface Subject {
    String operation();
}

--------------------------

@Slf4j
public class RealSubject implements Subject{
    @Override
    public String operation() {
        log.info("real subject call");
        sleep(1000);
        return "data";
    }

    private void sleep(int millis) {
        try{
            Thread.sleep(millis);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
    }
}

--------------------------

@Slf4j
public class CacheProxy implements Subject{

    private Subject subject;
    private String cacheValue;

    public CacheProxy(Subject subject) {
        this.subject = subject;
    }

    @Override
    public String operation() {
        log.info("proxy call");
        if (cacheValue == null){
            cacheValue = subject.operation();
        }
        return cacheValue;
    }
}

--------------------------
public class ProxyPatternClient {

    private Subject subject;

    public ProxyPatternClient(Subject subject) {
        this.subject = subject;
    }

    public void execute(){
        subject.operation();
    }


}
// sample
--------------------------

 @Test
 void cacheProxyTest(){
        Subject realSubject = new RealSubject();
        Subject cacheProxy = new CacheProxy(realSubject);
        ProxyPatternClient client = new ProxyPatternClient(cacheProxy);
        client.execute();
        client.execute();
        client.execute();

    }

결과

13:40:55.009 [main] INFO study.datajpa.pureproxy.proxy.code.CacheProxy - proxy call
13:40:55.010 [main] INFO study.datajpa.pureproxy.proxy.code.RealSubject - real subject call
13:40:56.015 [main] INFO study.datajpa.pureproxy.proxy.code.CacheProxy - proxy call
13:40:56.016 [main] INFO study.datajpa.pureproxy.proxy.code.CacheProxy - proxy call

profile
개발자로 입사했지만 정체성을 잃어가는중... 다시 준비 시작이다..

0개의 댓글