Proxy(프록시)의 뜻이 뭘까?
뭔가를 대신해준다? 누군가를 대체해준다?
프록시 패턴이란?
프록시는 다른 객체에 대한 대체 또는 자리표시자를 제공할 수 있는 디자인 패턴이다. 원래 객체에 대한 접근을 제어하므로, 요청이 원래 객체에 전달되기 전 또는 후에 무언가를 수행할 수 있도록 함.
그렇다면 프록시 패턴은 어떤 문제들을 해결할 수 있을까?
프록시 패턴이 해결할 수 있는 문제
특정 데이터베이스로의 쿼리 응답이 굉장히 느리다고 가정하자.
이 경우 여러 클라이언트들이 직접적으로 DB로 접근해서 쿼리를 날린다면 정말 더 느려질 것이다.
하지만 만약 아래와 같이 프록시 서버를 둔다면,
프록시 서버에서의 캐싱을 이용해서 DB로의 접근을 줄이고 프록시 서버에서 처리를 해줘 성능 향상을 도모할 수 있고 DB는 DB의 기능만을 수행하고 캐싱과 같은 부가적인 기능은 프록시 서버에서 처리해줄 수 있다. ⇒ SRP
프록시 패턴을 사용하는 방법 및 이유
그럼 어떻게 프록시 패턴을 사용할 수 있을까?
- 서비스 객체가 어떤 인터페이스를 구현하게 만든다. 프록시가 서비스 객체로 위장하기 위함이다.
- 서비스는 어떤 유용한 비즈니스 로직을 제공하는 클래스이다.
- 프록시 클래스에는 서비스 객체를 가리키는 참조 필드가 있고 요청의 처리( 초기화 지연, 로깅, 액세스 제어, 캐싱 등)를 완료하면, 그 후 처리된 요청을 서비스 객체에 전달한다. 일반적으로 프록시들은 서비스 객체들의 전체 수명 주기를 관리한다.
- 클라이언트는 같은 인터페이스를 통해 서비스들 및 프록시들과 함께 작동해야한다. 그러면 서비스 객체를 기대하는 모든 서비스 코드에 프록시를 전달할 수 있기 때문이다.
그럼 프록시 패턴을 사용하는 목적이 위에서 말했던 캐싱을 이용한 성능 향상뿐일까?? 아니다❌
⇒ 이런 개념 및 구조를 이용한 여러 목적을 가진 프록시 종류들이 있다. 그 중 자주 사용되는 몇 가지를 알아보자.
프록시의 자주 사용되는 종류
프록시의 종류는 굉장히 많지만 결국 다 같은 개념을 활용한 것
1️⃣ 원격 프록시
- 다른 JVM에 위치한 객체와 정보 주고 받기 ( 네트워크를 통한 원격 객체의 메서드 호출 )
- 예를 들면, 동작 중인 기계에 원격 모니터링 기능을 추가하고 싶다면 동작 중인 기계(원격 객체)의 메서드를 호출해서 보고서를 받는 기능을 수행할 수 있음.
- 예제
2️⃣ 캐시 or 로깅 프록시 :
- 진짜 객체가 가진 기능을 수행하면서 그 전과 그 후에 캐시에 저장, 로그에 출력, 트랜잭션 처리 등의 어떤 처리를 하는 기능을 수행할 수 있음.
- 진짜 객체에서는 자신이 가진 기능만을 수행해야하고 SRP를 깨지 않게끔 프록시에서 이 처리하고 싶은 기능들을 해줌.
- 예제
- 실행결과
- Payment라는 진짜 서비스 객체인 현금에 접근해서 서비스 로직을 수행할 때는 지불만 가능하다.
- 만약 내부에서 로깅과 같은 작업을 수행하게 된다면 SRP에 어긋나게 된다.
- 신용카드라는 프록시 객체에 접근해서 서비스 로직을 수행하면 현금의 기능을 그대로 이용하면서 로깅을 SRP에 어긋나지 않게 사용할 수 있다.
- Payment라는 진짜 서비스 객체인 현금에 접근해서 서비스 로직을 수행할 때는 지불만 가능하다.
3️⃣ 보호 프록시
- 접근 권한이 있으면 이용, 접근 권한이 없으면 이용하지 못하게 동작하여 보안적인 기능을 추가해줄 수 있음.
- 예제
- 실행결과
- WebManager라는 진짜 서비스 객체에 바로 접근한다면 권한 확인없이 일반인이어도 일급기밀을 볼 수 있음.
- WebLogin이라는 프록시 객체에 접근해서 서비스 로직을 수행하면 접근권한에 따라 로직을 나눠서 수행할 수 있음.
4️⃣ 가상 프록시
- 생성 및 초기화에 큰 리소스를 요구하는 객체가 존재할 때, 해당 객체는 생성되고도 사용되지 않는 경우가 있다.
- 이를 방지하기 위해서 진짜 필요하는 기능이 사용될 때까지 늦춰서 객체를 생성 혹은 초기화하는 것이다.
- 예제
- 실행결과
- 생성자와 함께 인스턴스가 생성된다고 하면 생성된 인스턴스가 오랜 기간 사용되지 않으면 리소스의 낭비가 됨.
- 진짜 필요로 하는 순간에 생성이 되면 리소스의 낭비가 없음. ⇒ Lazy Initialize
프록시 패턴의 장단점
👍 장점
- 클라이언트 측에서 알지 못하는 상태로 서비스 객체를 제어 가능
- 클라이언트들이 신경 쓰지 않게 서비스 객체 수명 주기를 관리 가능
- 서비스 객체가 준비되지 않았거나 사용할 수 없는 경우에도 작동가능
- OCP ⇒ 서비스나 클라이언트를 변경하지 않고도 새 프록시들을 도입가능
👎 단점
- 새로운 클래스들을 많이 도입해야하므로 코드가 복잡해질 수 있음.
- 서비스의 응답이 늦어질 수 있음.
다른 패턴과의 관계
- 데코레이터
- 데코레이터와 프록시는 자주 헷갈리는 개념이다. 왜냐면 둘 다 한 객체가 일부 작업을 다른 객체에 위임해야 하는 합성 원칙을 기반으로 하기 때문이다.
- 두 패턴의 구조는 비슷하지만 의도가 매우 다르다.
- 데코레이터는 타깃에 부가적인 기능을 부여해주는 것에 초점. 클라이언트 측에서 데코레이터의 합성을 제어함.
- 프록시는 자신의 서비스 객체의 수명 주기를 관리하고 접근 방법 제어를 하는 것에 초점.
- 어댑터
- 어댑터는 다른 인터페이스를 Wrapping된 객체에 제공함. 즉, 기존 인터페이스를 변경함.
- 프록시는 같은 인터페이스를 Wrapping된 객체에 제공함. 즉, 기존 인터페이스가 바뀌지 않음.
- 퍼사드
- 퍼사드는 복잡한 개체(entity)를 보호하고 자체적으로 초기화한다는 점에서 프록시와 유사함.
- 하지만 퍼사드 패턴과 달리 프록시 패턴은 자신의 서비스 객체와 같은 인터페이스를 가지므로 이들은 서로 상호 교환이 가능함.
Reference
Uploaded by N2T