프록시(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();
}
}