프록시(proxy) 패턴이란?
proxy : 대리자(surrogate)라고도 불린다. 다른 객체에 대한 접근을 제어하기 위한 대리자(비서) 역할을 하는 객체를 둔다.
proxy 패턴을 사용하는 이유
어떤 객체에 대한 접근을 제어하는 이유 중 하나는 그 객체를 사용할 수 있을 때까지 객체 생성과 초기화에 들어가는 비용 및 시간을 물지 않겠다는 것이다. 이미지를 예를 들어 보겠다. 이미지 프록시는 문서 편집기가 실제로 draw() 연산을 통해서 화면에 그리기 원할때만 실제 이미지를 생성한다. 프록시는 자신이 받은 메시지를 실제 이미지에 전달하고, 이미지 생성 후 이미지에 대한 참조를 계속 유지해야 한다.
프록시는 자신이 책임져야 할 이미지의 넓이와 높이를 한계 정보로 관리한다. 이는 이미지의 실제적 인스턴스 없이도 문서가 관리해야 하는 이미지의 크기에 대한 요청을 처리할 수 있게 된다.
proxy 패턴을 언제 활용할까?
- remote proxy : 서로 다른 주소 공간에 존재하는 객체를 가리키는 대표 객체로, 로컬 환경에 위치한다. 객체가 다른 주소 공간에 존재한다는 사실을 숨길 수 있다.
- 가상 프록시(virtual proxy): 요청이 있을 때만 필요한 고비용 객체를 생성한다. 처리를 최적화한다.
- 보호용 프록시(protection proxy) : 원래 객체에 대한 실제 접근을 제어한다. 이는 객체별로 접근 제어 권한이 다를 때 유용하다.
- 스마트 참조자(smart reference) : 실제 객체에 접근이 일어날 때 추가적인 행동을 수행한다. 아래는 전형적인 사용 예 3가지이다.
- 실제 객체에 대한 참조 횟수를 저장하다가 더는 참조가 없을 때 해당 객체를 자동으로 없앤다.
- 맨 처음 참조되는 시점에 영속적 저장소의 객체를 메모리로 옮긴다.
- 실제 객체에 접근하기 전에, 다른 객체가 그것을 변경하지 못하도록 실제 객체에 대해 lock을 건다.
보호용 프록시와 스마트 참조자는 객체가 접근할 때마다 추가 관리를 책임진다. (객체를 생성할 것인지, 삭제할 것인지)
proxy 패턴의 또다른 최적화, 기록 시점 복사 (copy-on-write)
요청이 들어올 때만 객체를 생성한다. 사본이 변경되지 않고 원본과 같다면 새로 생성할 필요가 없다. 프록시를 사용해서 복사 절차를 미룸으로써, 시스템을 최적화한다.
이 기능을 가능하게 하려면 원본의 참조 카운트를 관리해야 한다. 프록시를 복사하는 연산은 이 원본에 대한 참조 카운트를 증가시키는 일 외에는 다른 일은 하지 않는다. 사용자가 이 원본을 수정하는 연산을 요청할 때 프록시가 실제로 복사를 진행하여 사본이 별도의 값을 가지게 한다. 이렇게 하면 원본에 대한 참조자 수는 줄어들고, 이 과정을 반복하여 참조 카운트가 0이 되면 대상을 삭제한다.
다이나믹 프록시란?
런타임에 특정 인터페이스들을 구현하는 클래스 또는 인스턴스를 만드는 기술. 클래스 기반의 프록시를 만들지 못한다. (인터페이스만 가능)
출처: GoF의 디자인 패턴