Easy Understanding

웹 백엔드 관점으로 본 디자인 패턴 정리(11) - 프록시 패턴(Proxy Pattern) 본문

Study

웹 백엔드 관점으로 본 디자인 패턴 정리(11) - 프록시 패턴(Proxy Pattern)

appleg1226 2022. 5. 8. 19:46

 

- 필요 개념: 상속, 컴포지션
- 활용도:사용할일이 많지는 않지만, 읽을 일이 많은 개념
- 난이도: 구조 자체는 심플하지만, 관련 기술이 복잡하다.
- 패턴이 필요한 상황: 접근 제어, 메서드 기능 추가 다양하게 활용 가능

 

프록시의 구현 방법은 데코레이터 패턴과 비슷한 면이 많다.

 

interface A {
  void doSomething();
}

class AImpl implements A {
  public void doSomething(){
    ...
  }
}

이런 간단한 인터페이스와 클래스가 있다고 하자.

이 doSomething() 바깥에서 특수한 처리를 하고 싶다면

(누가 요청했는지 확인해서 막는다든지, 로깅을 하고 싶다든지 정말 다양한 이유로)

이렇게 처리하면 된다.

class AProxy implements A {
  private A a;
  
  public AProxy(A a) {
    this.a = a;
  }
  
  public void doSomething(){
    // 여기서 전처리를 하거나
    
    a.doSomething();
    
    // 여기서 후처리를 할 수 있다
  }
}

 

프록시의 목적은 데코레이터의 '기능 추가' 목적과는 다르다.

데코레이터에서는 내부 메서드의 행위를 통해서 새로운 결과물을 낼 수도 있는 패턴이지만,

프록시는 그와 다르게 내부 메서드의 결과물에는 관심이 없다.

가공하는 것도 지양해야 한다.

 

프록시에서는 내부 처리는 그대로 진행되게 내버려두어야 한다.

사용하는 클라이언트 입장에서는 메서드의 동작이 기존과 같도록 느껴지게 해야 한다.

그게 프록시라는 뜻(대리자)에 가장 맞는 것 아닐까 싶다.

 

Proxy in Spring

스프링에서는 프록시를 많이들 사용한다.

아마 '스프링 프록시'라고 검색하면 가장 많이 나오는 문서는 AOP와 관련된 문서들일 것이다.

또한 @Scope 내부에는 'proxyMode = ScopedProxyMode.TARGET_CLASS' 같은 설정도 존재한다.
스프링은 프레임워크 내부 구현에 프록시를 적극 사용한다.

디버깅 trace를 보다면 이 proxy와 관련된 코드들도 자주 마주칠 수 있다.

 

이러한 이유로 프록시는 사용하지 않더라도 반드시 알아야 하는 패턴 중 하나이다.

기존 객체의 행위를 가로채서 수많은 행위를 할 수 있기 때문에 프레임워크 단위에서 사용하기에 좋은 기술이다.

 

JDK의 Dynamic Proxy

스프링에서 프록시를 사용할 땐 JDK의 Dynamic ProxyCGLIB이라는 기술을 사용하는데, 

여기에선 기본적으로 사용되는 Dynamic Proxy을 간단하게 정리해보려고 한다.

 

자바 라이브러리 중에 java.lang.reflect.Proxy 라는 패키지에서 프록시를 import하여 사용할 수 있다.

 

원래대로라면 위의 예시처럼 프록시를 사용하기 위해서 클래스를 하나 선언할 수 있지만,

자바에서는 이걸 자동으로 만들어주는 메서드를 제공해준다.

 

JDK 다이내믹 프록시를 사용하려면 다음처럼 사용하면 된다.

일단 앞의 두 파라미터는 설정값이라 넘어가고, 핸들러가 중요하다.

A a = (A) Proxy.newProxyInstance(
  A.class.getClassLoader(), new Class[]{A.class}, 핸들러(기능추가부분)
);

 

위의 프록시 클래스에서 작성한 전후 로직을 저 핸들러 내부에 작성하면 된다.

InvocationHandler 인터페이스를 구현해서 이 메서드를 채우면 되는데 리플렉션 라이브러리를 이용해서 작성하면 된다.

public Object invoke(Object proxy, Method method, Object[] args){
  ...
}

 

아마도 스프링 같은 특정 프레임워크를 사용한다면 이 프록시를 직접 사용할 일은 적을 것이다.

AOP로 웬만한 동작은 다 커버되기에, AOP를 열심히 공부하면 된다.

 

정리하자면,

프록시 패턴은 본인이 직접 코어한 로직을 개발해야할 일이 있다면 사용할 순 있겠지만,

아마 읽을 때 유용할 일이 더 많은 것 같은 패턴이다.