"다른 객체에 대한 접근을 제어하기 위한 대리자 또는 자리채움자 역할을 하는 객체를 둡니다"
-Gang Of Four-
네트워크 연결
, 메모리 안의 커다란 객체
, 파일
, 복제할 수 없거나 수요가 많은 리소스
의 인터페이스의 역할을 수행🤔 프록시 활용 예시
- 객체의 속성, 변환 등을 보완 → 보안, 데이터 검증, 캐싱, 로깅에 사용
- 프록시 서버
- 복합적인 오브젝트들의 다수의 복사본이 존재해야만 하는 상황
→ 프록시 패턴은 애플리케이션의 메모리 사용량을 줄이기 위해서 플라이웨이트 패턴과 결합된 형태로 나올 수도 있음.- EX) 용량이 큰 이미지와 글이 같이 있는 문서를 모니터 화면에 띄울 때
→ 이미지 파일은 용량이 크고 텍스트는 용량이 작다.
→ 텍스트는 빠르게 나타나지만 그림은 조금 느리게 로딩
→ 먼저 로딩이 되는 텍스트라도 먼저 나오는게 좋다. (다 로딩될 때까지 기다리기 힘드니까~)
→ 텍스트 처리용 프로세서, 그림 처리용 프로세스를 별도로 운영해야 함.
→ 프록시 패턴을 이용~
🤔언제 사용하나요?
- 한 객체에 대한 접근을 제어해야 할 때
- 중요한 개체에 접근할 때 client가 필요한 접근 권한을 가지고 있는지 확인할 수 있어야 할 때
- 객체에 접근할 때 추가 기능을 제공해야 할 때
- 무거운 처리(사이즈가 큰 인스턴스 생성 등)를 필요할 때만 처리 하도록 지연시키고 싶을 때
Subject 구현체(Proxy)로 Request() 함수를 호출할 때 RealSubject를 참조하고 있는 Proxy가 RealSubject를 대리하는 구조, 즉 Proxy는 realSubject.operation()으로 호출
Subject(주체, interface)
: Proxy와 RealSubject를 동일시하기 위한 인터페이스(API)를 정의
: 이 객체를 통해 Client는 Proxy와 RealSubject의 차이를 의식할 필요 없음
Proxy(대리인, class)
: Client의 요구를 할 수 있는 만큼 처리
: 자신만으로 처리할 수 없으면 RealSubject에게 처리를 맡김 -> 정말 RealSubject가 필요할 때 RealSubject를 생성
: Subject에서 정해지는 인터페이스(API)를 구현
RealSubject(실제 주체, class)
: Proxy에서 감당할 수 없는 일이 발생했을 때 등장
: Proxy와 마찬가지로 Subject에서 정해져 있는 인터페이스(API)를 구현
Client(의뢰인)
: Proxy 패턴을 사용하는 역할
: 보통 Main 클래스를 의미함
❗대리인(Proxy)과 본인(RealSubject)을 분리할 필요가 있는가?
- 분리 하지 않고 RealSubject에 처음부터 지연평가의 기능(필요하면 그 때 인스턴스를 생성하는 기능)을 추가해도 된다.
- 그러나 분리해서 프로그램의 부품화를 만들면 개별적으로 수정이 가능 즉, 분할해서 통치!!
- 즉 Subject 인터페이스에서 선언되어 있는 메소드 중에서 무엇을 Proxy가 처리할 것인지 쉽게 변경 가능할 수 있고 RealSubject에서 수정할 필요가 전혀 없다.
EX) 지연 평가를 실행시키고 싶지 않다
Client에서 바로 RealSubject 인스턴스를 생성
(어차피 Proxy든 RealSubject든 Subject의 인터페이스를 모두 구현하니까)
❗대리와 위임
- Proxy가 혼자 처리할 수 있는 일은 Proxy가 처리
- Proxy가 처리할 수 없을 때 RealSubject에 위임한다. (proxy 클래스에서 RealSubject의 메소드를 호출하는 부분에 해당)
❗투과적이란?
- Proxy와 RealSubject는 같은 Subject라는 인터페이스로 구현하고 있음
→ client는 실제로 호출하는 곳이 Proxy든 RealSubject든 상관하지 않는다.- 즉, RealSubject를 직접 이용해도 중간에 Proxy가 들어와도 문제없이 사용 가능
→ 이를 Proxy는 투과적이라고 함!
EX) 후기 초기화(lazy instantiation)
용량이 큰 이미지를 백그라운드 프로세스에서 네트워크를 통해 가져오는 동안(데이터베이스 접근은 데이터가 실제로 사용되기 전까지 프록시가 대신) 사용자는 이미지가 이미 그곳에 있다고 생각한다.
: 가상 프록시는 복사 수정 전략을 구현하는 데에도 유용
→ 객체의 복사 본을 요청받으면 프록시는 단순히 원본 객체에 대한 레퍼런스만을 갖는다그리고 복사본에 대한 수정 요 청이 들어오면 이때 비로소 프록시가 원본 객체를 실 제로 복사하게 된다
❗ Example
- 초기화에 시간이 걸리는 기능이 많이 존재하는 대규모 시스템
→ 기동 시점에서는 이용하지 않는 기능까지 전부 초기화하면 어플리케이션의 기동에 시간이 많이 걸린다는 문제 발생
→ 실제로 해당 기능을 사용할 단계가 되어서 초기화 하도록 하는게 좋다!!- 문서 안에 그래픽 오브젝트(화상 등) 를 포함한 문서 에디터
→ 그래픽 오브젝트를 생성하 때 화상 파일을 읽는 등 많은 시간이 걸리기 때문에 모든 그래픽 오브젝트를 생성하는 것은 시간 낭비!
→ 각각의 그래픽 오브젝트를 화면에 표시할 때 생성하는 것이 좋다.
public interface Image {
void display();
}
public class RealImage implements Image {
private String fileName; // Image file 이름
public RealImage(String fileName){
this.fileName = fileName;
loadFromDisk(fileName);
}
@Override
public void display() { // 인터페이스 구현
System.out.println("Displaying " + fileName);
}
private void loadFromDisk(String fileName){
System.out.println("Loading " + fileName);
}
}
public class ProxyImage implements Image{
private RealImage realImage; // 실제 Image class
private String fileName;
public ProxyImage(String fileName){
this.fileName = fileName;
}
@Override
public void display() { // Image 인터페이스 구현
if(realImage == null){ // 실제 Image 클래스를 생성
realImage = new RealImage(fileName);
}
realImage.display();
}
}
public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ProxyImage("test_10mb.jpg");
//image will be loaded from disk
image.display();
System.out.println("");
//image will not be loaded from disk
image.display();
}
}
//result
Loading test_10mb.jpg
Displaying test_10mb.jpg
Displaying test_10mb.jpg
public interface Printable {
void setPrinterName(String name);
String getPrinterName();
void print(String string);
}
Printer 클래스
: 생성자는 heavyjob을 싱행하고 있음
Printable 클래스
: Printer Proxy와 Printer를 동일시 하기 위한 것
PrinterProxy 클래스
: 대리인
: setPrinterName과 getPrinterName을 호출해도 Printer 인스턴스는 생성되지 않음
: Printer 인스턴스가 생성되는 것은 본인(Printer 클래스의 인스턴스)이 정말로 필요할 때
: Printer 클래스는 PrinterProxy의 존재를 모른다는 점!! 자신이 PrinterProxy를 경유해서 호출되고 있는지 아니면 직접 호출되고 있는지 Printer 클래스는 모른다.
면접을 위한 CS 전공지식 노트
Java 언어로 배우는 디자인 패턴 입문
GOF Design Pattern
Proxy pattern
프록시 패턴-위키백과
Design Patterns - Proxy Pattern
프록시 패턴 (Proxy Pattern)-기계인간
[Design Pattern] 프록시 패턴(Proxy Pattern)에 대하여