이재만박사 2017. 2. 9. 22:48

* Proxy 패턴


- 대리 객체를 통해 원래 객체의 작업을 수행하게 만드는 패턴



* 예제


- 웹으로 만화 서비스 제공

- 이미지 파일로 서비스 제공

- 서비스 요청에 따른 반응 시간 오래 걸림

- 특정 시간대에 서비스 요청이 폭주


- 어떻게 하면 적은 자원을 사용하면서도 서비스 요청이 폭주하는 시간대에도 서비스 요청에 따른 반응 시간을 안정되고 빠르게 유지

-어떻게 한정된 자원으로 안정되고 빠른 만화 서비스를 제공


- 이 문제를 해결하기 위해 먼저 서비스 요청이 어떤 단계의 작업을 거쳐 처리되는지 세분화

- 각 단계에서 작업에 소요되는 시간 측정

- 해야할 과제는 서비스 요청을 처리하는데 걸리는 전체적인 시간을 단축해서 서비스 요청이 폭주하더라도 서비스   요청 처리가 빠르게 이루어지도록 하는 것


- 이 경우 두 가지 : 네트워크를 통해 서버에서 웹 브라우저로 이미지 파일을 전송

                      웹 서버 프로그램이 디스크로부터 이미지 파일의 내용을 읽어내는 작업


- 효과적인 방법은 웹 서버가 디스크로부터 이미지 파일을 읽어들이는 데 걸리는 시간을 줄이는 것



1. 기본적인 방법 : 단순 캐싱 방식


- 디스크의 처리 속도가 느리기 때문

- 디스크의 경우 파일을 읽어들이는 요청이 한 꺼번에 폭주하더라도 이 요청을 동시에 처리할 수 없다는 단점

- 디스크보다 훨씬 빠른 처리 속도를 가진 기억 공간을 활용할 필요

- 이 기억 공간을 동시에 접근

- 모든 서비스 요청들이 평균적으로 비슷한 반응 속도


- 모든 이미지 파일을 메모리에 올릴 수 없으므로 최근 사용된 이미지 파일을 위주로 그 내용을 메모리 상에 캐싱

- 서비스 요청이 있을 경우 이를 활용


- 최근에 서비스 요청된 이미지 파일들은 메모리 상에 읽어서 서비스 하고, 그렇지 않으면 디스크로부터 파일 읽기

- 이용자가 보고 싶어 하는 만화는 최근에 서비스를 시작, 또는 인기가 높은 만화로 집중

- 따라서 대부분의 서비스 요청을 메모리 상에 저장된 내용을 읽어 서비스 가능

- 이러한 캐싱 방법을 어떤식으로 구현하도록 설계하는 것이 바람직한가?



- 클라이언트 모듈의 기본적인 동작


1. 사용자에 의해 요청된 이미지 파일이 메모리 상에 캐싱 되어 있는지 검사

2. 만약 이미 캐싱되어 있다면 읽어서 그대로 서비스 진행

3. 만약 캐싱되어 있지 않으면 디스크로부터 이미지 파일을 직접 읽어서 서비스

4. 읽혀진 이미지 파일은 메모리 상에 캐싱되어 관리

5. 가장 오래 사용되지 않은 캐싱 정보를 삭제하고 새로운 이미지 파일을 캐싱


- 이미지 파일을 캐싱해서 사용할 경우 이미지 파일 캐싱을 위한 클래스는 두 개가 필요


1. 이미지 파일을 캐싱하고 관리하는 클래스 - ImageFileCache

2. 메모리 상에 캐싱되어 있지 않은 이미지 파일을 디스크로부터 읽어들이기 위한 클래스 - ImageFile


- 이 방식은 클라이언트가 일일이 원하는 이미지 파일이 캐싱되어 있는지 확인하고, 없으면 디스크 읽어 캐싱

- 클라이언트 코드가 복잡하고 지저분해 짐

- 클라이언트는 캐싱하든, 디스크에서 직접 읽든 이미지 파일만 얻으면 됨



2. Proxy 패턴


- 새로운 클래스를 만들지 않고 원하는 두 가지 역할을 동시에 하는 방법

- 클라이언트는 ImageFileCache 클래스 객체에게 원하는 이미지 파일이 캐싱되어 있는지 확인

- 캐싱되어 있지 않으면 ImageFile 클래스 객체를 이용해서 디스크로부터 이미지 파일 읽어 들임

- 이미지 파일이 캐싱되어 있지 않는 경우 이를 처리하는 역할만 ImageFileCache 클래스가 같이 수행하면 된다


- 문제는 ImageFileCache 클래스와 ImageFile 클래스가 외부로 제공하는 인터페이스가 다르다

- ImageFileCache 클래스와 ImageFile 클래스의 상위에 공통된 인터페이스를 가진 추상클래스를 정의해 주는 것



- 기본적으로 어떤 역할을 수행하고 있는 클래스가 존재할 때 그 클래스가 제공하는 기능이나 역할을 그대로 활요하면서 부가적인 기능이나 역할을 수행해주기 위해 새로운 클래스를 정의하고 Client의 모든 요청을 새로 정의한 클래스 객체를 거쳐 원래의 클래스 객체에게 전달하는 방식의 클래스 구조를 Proxy 패턴


- 이 때 새로 정의한 클래스는 원래 존재하던 클래스와 동일한 인터페이스를 제공

- 그 이유는 기존 클래스의 인터페이스를 활용하는 형태로 작성된 Client 프로그램을 수정하지 않고

새로 정의된 클래스를 활용할 수 있도록 하기 위함