본문 바로가기

ACC/디자인 패턴 스터디

[디자인 패턴 스터디] 10. 프록시 패턴

프록시 패턴

  • 프록시 서버: 클라이언트와 서버의 통신을 제어하는 대리 서버.
  • 프록시 패턴: 특정 객체로의 접근을 제어하는 대리 객체를 제공하는 패턴.

프록시 패턴의 구조

프록시 패턴은 클라이언트 객체, 서비스 객체, 스텁(프록시 객체), 스켈레톤(서비스 객체쪽 보조 객체)로 이루어진다.

 


필요성

만약 기존의 모니터링 프로그램이 있었다고 할 때, 이를 원격으로 사용해야 한다면?

물론 서버 개념을 도입해서 아예 코드를 갈아엎을 수도 있겠지만 변경을 최소화할 수 있다. 또한 기존 프록시가 갖는 장점(원격 객체 접근 제어 등)을 프록시 패턴으로 얻을 수 있다.


RMI

지금까지의 패턴은 전부 로컬에서 이루어졌지만, 프록시 패턴(원격 프록시)은 로컬에서만 이루어지지 않는다. 애초에 로컬에서 동작하는 것처럼 서버와 데이터를 주고 받는 것이 프록시 패턴이기 때문이다.

그렇기 때문에 서버-클라이언트 개념이 도입되어야 하는데, 자바에서는 이를 RMI로 처리한다.

RMI는 RMI 레지스트리를 확인함으로써 서로 다른 힙에서 서로 정보를 주고 받을 수 있는데, RMI 레지스트리는 특정 주소, 특정 이름으로 지정해서 사용할 수 있다. (ex. "rmi://127.0.0.1/Test")

이때 정보교환은 직렬화를 통해서 byte단위로 전달한다.

 


작동 순서

순서가 개인적으로 헷갈려서 정리하기로 했다.

 

1. RMI 레지스트리 on

2. RMI 레지스트리에 서비스를 등록 (rebind). 등록하는 코드를 따로 작성한다.

3. 서비스 실행

4. 클라이언트 실행

5. 클라이언트가 원격 서비스로 함수 실행 요청

6. RMI 레지스트리에서 서비스를 찾음 (lookup). 이때 스텁이 반환된다.

7. 스텁이 스켈레톤에게 함수 실행 요청

8. 스켈레톤이 서비스에게 함수 실행 요청

9. 서비스는 함수를 실행하고 스켈레톤에게 결과를 반환

10. 스켈레톤이 결과를 직렬화

11. 스켈레톤이 직렬화된 결과를 스텁에게 넘김

12. 스텁이 받은 결과를 역직렬화

13. 클라이언트가 스텁에게 결과를 받음.

 

그림으로 표현

 


서비스 코드 리팩토링

서비스 코드는 크게 달라지지 않는다. 원격 인터페이스(Remote를 상속받는)를 만든다.

그리고 원격 통신을 할 수 있도록 클래스에 UnicastRemoteObject를 상속받게 한다. 또한 원격 인터페이스도 구현한다.

원격 인터페이스가 반환하는 모든 함수는 직렬화가 가능한 형태로 변경한다. (extends Serializable)

원격 통신을 할 것이므로 예외 처리에 주의한다.

 


클라이언트 코드 리팩토링

기존에 사용하던 서비스 구상 클래스 대신 원격 인터페이스를 사용한다. 그리고 원격 인터페이스 타입을 받아올 때는 원격 통신으로 받아온 것이므로 예외 처리에 주의한다.

 


추가

RMI 레지스트리에 서비스를 등록해주는 역할을 하는 클래스와 클라이언트가 최종적으로 실행할 main함수가 들어간 클래스까지 추가하면 완성

 


가상 프록시

사실 지금까지 봤던 것은 프록시 패턴 중에서도 원격 프록시 패턴이었다. 가상 프록시는 생성에 큰 비용이 드는 객체를 대신한다. 

예를 들어서 어떤 앱을 실행하는 데에는 오랜 시간이 걸리지만 보통은 그 시간동안 로딩창을 보여주거나, 앱이 실행되고 있음을 알려주는 어떤 장치가 있다. 이런 장치가 가상 프록시에 해당한다.