
프록시(Proxy)는 대리라는 의미로 네트워크에서 프록시 서버(Proxy Server)는 클라이언트가 자신을 통하여 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 컴퓨터 시스템이나 응용프로그램을 말한다.Forward Proxy (정방향 프록시)
▶︎ 정방향 프록시 서버는 회사 내부 디바이스가 클라이언트인 경우에 유용하다. 네트워크 데이터를 외부인으로부터 보호하고 익명화하는 것이 가능하다.

Reverse Proxy (역방향 프록시)
중간 서버이다.모니터링하고 차단한다.방문자 트래픽을 검사하여 무단 활동이 있는지 확인한다.특정 트래픽 소스를 차단하도록 역방향 프록시를 구성할 수 있다.보안 정책을 준수하는 요청만 애플리케이션 서버에 전달할 수 있다.
개인 정보 보호
: 프록시 서버 없이 클라이언트가 서버에 요청 시 IP가 노출되지만 프록시 서버 사용시 프록시 서버 IP 주소가 노출되기 때문에 개인 정보를 보호할 수 있다.
캐시 사용
: 프록시 서버에 이전에 했던 요청들을 캐싱을 통해 저장을 해두기 때문에 같은 내용을 재요청시 서버를 거치지 않고 데이터를 주고 받을 수 있다. 이 과정에서 시간을 줄어들어 속도 향상에 도움을 준다.
인터넷 사용 제어
: 이는 자체 프록시를 설정하는 회사 또는 기타 사용자가 주로 사용한다. 프록시를 제어하는 경우 일부 웹 주소를 금지하여 자녀, 직원 또는 프록시를 통해 실행되는 네트워크를 사용하는 사람이 원하지 않는 곳으로 가지 못하도록 할 수 있당.
접속 우회
: 접속한 클라이언트의 실제 IP 주소를 알 수 없기 떄문에 자신의 위치를 숨길 수 있다. 이는 프록시 서버를 통해 접속을 우회할 수 있다는 것이다.
방화벽 역할
: 개인 사용자에서 기업에 이르기까지 프록시는 온라인에서 악의적인 공격을 방어하는 방화벽 역할을 할 수 있다. 그리고 가장 기본적인 수준에서 장치의 온라인 주소를 가려 보안을 강화할 수 있다.
프록시 서버와 가상 프라이빗 네트워크(VPN)는 조직의 내부 기업 네트워크와 공용 인터넷을 중개하는 기술이다.
프록시 서버와 VPN의 유사점
모든 수신 및 발신 네트워크 트래픽을 프록시 서버, VPN 또는 둘 다를 통해 라우팅 할 수 있다.
프록시 서버와 가상 프라이빗 네트워크(VPN) 둘 다 클라이언트의 개인 정보 보호 및 보안을 강화한다. 둘 다 클라이언트의 IP 주소를 익명화한다.
프록시 서버와 VPN의 차이점
클라이언트 서버 통신에서 하는 역할
들어오는 트래픽
나가는 트래픽
로드 밸런싱
프록시 패턴(Proxy Pattern)▶︎ 프록시 패턴은 디자인 패턴 중 구조 패턴에 해당한다.
Subject(주체)
: 프록시와 실제 서비스 객체가 모두 구현하는 공통 인터페이스이다. 이 인터페이스를 통해 클라이언트는 프록시와 실제 서비스 객체를 동일한 방식으로 사용할 수 있다.
RealSubject(실제 주체)
: 주체의 실제 구현으로 클라이언트가 직접 접근하려는 실제 서비스 객체라고 할 수 있다.
Proxy(프록시)
: 실제 주체(RealSubject)에 대한 대리자 역할을 하는 객체이다. 주로 클라이언트와 실제 주체 사이에 위치하며, 클라이언트의 요청을 중개하고 추가 기능을 수행할 수 있다.
Client(클라이언트)
: Subject 인터페이스를 이용하여 프록시 객체를 생성해 이용한다. 클라이언트는 프록시를 중간에 두고 프록시를 통해서 RealSubject와 데이터를 주고 받는다.

가상 프록시(Virtual Proxy)
: 가상 프록시는 실제 객체를 대신하여 비용이 많이 드는 작업을 지연시키는 데 사용된다. (지연 초기화 방식)
실제 객체가 필요한 시점에 생성되거나 초기화되며, 그 전에는 가상 프록시만 존재한다.
이미지 뷰어에서 이미지 로딩을 미리보기로 시작하고 필요할 때만 전체 이미지를 로드하는 경우에 사용된다.
원격 프록시(Remote Proxy)
: 원격 프록시는 분산 시스템에서 객체가 다른 머신 또는 위치에 존재할 때 사용된다. 클라이언트는 로컬 프록시를 통해 원격 객체에 액세스하고, 실제로는 원격 서버에서 데이터를 가져온다. 원격 프록시는 원격 서비스에 대한 통신을 추상화하고 관리한다.
보호 프록시(Protection Proxy)
: 보호 프록시는 객체에 대한 액세스를 제어하여 보안을 강화한다.(접근 권한)
클라이언트가 객체에 직접 접근하지 못하도록 권한 검사를 수행하거나 암호화를 해독하는 등의 보안 기능을 제공한다. 보호 프록시는 보안 감시, 인증 및 권한 부여에 사용된다.
로깅 프록시(Logging Proxy)
: 대상 객체에 대한 로깅을 추가하려는 경우 사용한다. 프록시는 서비스 매서드를 실행하기 전에 로깅을 하는 기능을 추가하여 재정의한다.
캐싱 프록시(Caching Proxy)
: 캐싱 프록시는 클라이언트 요청의 결과를 캐시하고 이 캐시의 수명 주기를 관리한다. 이는 이전에 수행한 작업의 결과를 캐시에 저장하여 동일한 요청에 대한 반복 작업을 피하고 성능을 향상시킨다. 캐싱 프록시는 주로 데이터베이스 쿼리나 웹 페이지에서 사용된다.
▶︎ 이 외에 스마트 프록시(Smart Proxy), 복잡성 감소 프록시 (Complexity Reduction Proxy), 동기화 프록시 (Synchronization Proxy) 등이 있으며, 프록시 패턴은 다양한 상황에서 다양한 종류로 활용될 수 있다.
개방 폐쇄 원칙(OCP) 준수단일 책임 원칙(SRP) 준수객체를 제어하거나 생명 주기를 관리할 수 있다.코드 복잡도가 증가한다.동적 프록시(Dynamic Proxy) 기법을 이용해서 해결할 수 있다.지연 로딩
: 실제 객체가 필요한 시점에 생성하거나 초기화한다. 이를 통해 성능을 최적화할 수 있다.
보안
: 프록시는 접근 제어 및 권한 검사를 수행하여 보안을 강화할 수 있다.
캐싱
: 프록시는 결과를 캐싱하여 동일한 요청에 대해 중복 작업을 방지하고 성능을 향상시킨다.
원격 액세스
: 원격 서버와의 통신을 관리하고 결과를 캐싱하여 원격 서비스에 대한 액세스를 최적화할 수 있다.
클라이언트 코드 분리
: 클라이언트는 실제 객체가 아니라 프록시와 상호작용하므로 클라이언트 코드가 간결해지고 객체와 클라이언트 코드 간의 결합도가 낮아진다.
서비스 확장 및 변경 용이성
: 클라이언트와 서비스 객체 사이에 프록시를 두면 새로운 기능을 추가하거나 기존 기능을 변경하기가 더 쉬워지고 클라이언트 코드 수정 없이 프록시를 교체할 수 있다.
: 이미 요청된 웹 페이지를 캐싱하여 동일한 요청이 다시 들어올 때 웹 페이지를 다시 다운로드 하지 않고 캐시된 페이지를 반환한다.
import java.util.HashMap;
import java.util.Map;
// 웹 페이지 인터페이스
interface WebPage {
void display();
}
// 실제 웹 페이지 클래스
class RealWebPage implements WebPage {
private String url;
public RealWebPage(String url) {
this.url = url;
loadPage();
}
private void loadPage() {
System.out.println("Loading web page: " + url);
}
public void display() {
System.out.println("Displaying web page: " + url);
}
}
// 웹 페이지 캐시 프록시 클래스
class WebPageCacheProxy implements WebPage {
private Map<String, RealWebPage> cache = new HashMap<>();
private String url;
public WebPageCacheProxy(String url) {
this.url = url;
}
public void display() {
if (cache.containsKey(url)) {
System.out.println("Retrieving web page from cache: " + url);
} else {
RealWebPage realWebPage = new RealWebPage(url);
cache.put(url, realWebPage);
}
cache.get(url).display();
}
}
public class ProxyPatternExample {
public static void main(String[] args) {
// 웹 페이지 요청과 캐시를 비교
WebPage realPage1 = new RealWebPage("https://www.example.com/page1");
WebPage proxyPage1 = new WebPageCacheProxy("https://www.example.com/page1");
WebPage realPage2 = new RealWebPage("https://www.example.com/page2");
WebPage proxyPage2 = new WebPageCacheProxy("https://www.example.com/page2");
// 첫 번째 페이지 요청 시 실제 페이지를 로드하고 캐싱합니다.
proxyPage1.display();
// 두 번째 페이지 요청 시 캐시된 페이지를 사용합니다.
proxyPage1.display();
// 세 번째 페이지 요청 시 실제 페이지를 로드하고 캐싱합니다.
proxyPage2.display();
}
}
: 가상 프록시 패턴을 사용하여 이미지 로딩을 구현한다. 가상 프록시는 이미지를 필요할 때만 로드하고, 그렇지 않은 경우에는 미리보기 이미지만 표시한다.
// 이미지 인터페이스
interface Image {
void display();
}
// 실제 이미지 클래스
class RealImage implements Image {
private String filename;
public RealImage(String filename) {
this.filename = filename;
loadFromDisk();
}
private void loadFromDisk() {
System.out.println("Loading image: " + filename);
}
public void display() {
System.out.println("Displaying image: " + filename);
}
}
// 가상 프록시 이미지 클래스
class ProxyImage implements Image {
private RealImage realImage;
private String filename;
public ProxyImage(String filename) {
this.filename = filename;
}
public void display() {
if (realImage == null) {
realImage = new RealImage(filename);
}
realImage.display();
}
}
public class ProxyPatternExample {
public static void main(String[] args) {
// 실제 이미지 로딩과 가상 프록시 이미지 로딩 비교
Image realImage = new RealImage("large_image.jpg");
Image proxyImage = new ProxyImage("small_image.jpg");
// 이미지를 처음 로딩할 때 실제 이미지가 로드됩니다.
realImage.display();
// 이미지를 처음 로딩할 때 가상 프록시 이미지가 로드되며, 이후에는 로드되지 않습니다.
proxyImage.display();
proxyImage.display();
}
}