본문 바로가기
디자인 패턴

[Design Pattern] 프록시 패턴

by 감자b 2024. 12. 26.

프록시란 대리자라는 의미로 클라이언트가 원본 객체를 이용하는 것이 아닌 대리자를 거쳐서 원본 객체에 접근하는 디자인 패턴이다.

이렇게 중계 역할을 하는 프록시 객체가 되려면, 클라이언트는 원본 객체에게 요청을 한 것인지, 프록시에게 요청을 한 것인지 몰라야 한다.

따라서 프록시는 원본 객체와 같은 인터페이스를 사용해서 구현하며, 이로 인해 대상 객체를 프록시로 변경해도 클라이언트 코드를 변경하지 않을 수 있다.


프록시 패턴 구조

 

Subject (공통 인터페이스)

  • 실제 객체와 프록시 객체가 공통으로 구현해야 하는 인터페이스
  • 클라이언트는 해당 인터페이스를 통해 실제 객체와 프록시 객체를 동일하게 사용할 수 있다.

 

public interface Subject {
     String operation();
}

 

RealSubject (실제 객체)

  • 실제 작업을 수행하는 객체
public class RealSubject implements Subject {
	@Override
	public String operation() {
		System.out.println("RealSubject.operation")
		try {
			Thread.sleep(millis);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	return "data";
}

 

Proxy (프록시 객체)

  • RealSubject의 대리자 역할로 프록시는 RealSubject에 대한 참조를 통해 요청을 위임하거나 제어한다.
    • 흐름 제어가 목적이며 결과를 조작, 변경시키면 안된다.
  • 클라이언트의 요청을 받아 RealSubject에 전달하거나, 그 전에 추가 작업(로깅, 접근 제어 등)을 수행
public class Proxy implements Subject {
	private Subject target; // 실제 객체에 대한 참조
	private String value;
    
	public CacheProxy(Subject target) {
		this.target = target;
	}

	@Override
	public String operation() {
		System.out.println("Proxy.operation");
		if (value == null) {
			value = target.operation();
		}
		return value;
	}
}

 

  • Client
    • 클라이언트는 프록시를 통해서 RealSubject와 데이터를 주고 받는다.
public class Client {
	private Subject subject;
	
	public Client(Subject subject) { // 프록시를 주입 받음.
		this.subject = subject;
	}

	public void operation() {
		subject.operation();
	} 
}

런타임 시점에 의존 관계가 Client → Proxy → RealSubject 가 된다.

 

클라이언트 입장에서는 프록시를 호출한 건지, 실제 객체를 호출한 건지 알 수 없으며 기존 객체를 수정할 수 없을 때 접근 제어를 하고 싶은 경우 클라이언트의 코드를 변경하지 않고 자유롭게 프록시를 추가할 수 있다.

 

프록시 패턴의 장단점

장점

  • 개방-폐쇄 원칙 준수
    • 기존 코드를 변경하지 않고 새로운 기능 추가 가능
  • 단일 책임 원칙 준수
    • 원본 객체는 자신의 기능에 집중할 수 있고, 부가 기능은 프록시가 처리함으로써 다중 책임 회피 가능
  •  코드 복잡성 감소

단점

  • 추가해야 할 기능이 많다면 프록시 클래스를 그만큼 만들어야 하므로 코드 복잡성 증가
  • 프록시 객체에 자원에 많은 경우 응답 시간이 약간 지연될 수 있음