1. 프록시 패턴
Proxy 는 대리인이라는 뜻이다. 아래 예시를 보자.

문지기 앞단에 Proxy(대리인) 를 두고, 동물들 중 ex. 쥐가 오면 쫓아내고, 쥐가 아닌 동물들은 성으로 향하게 할 수 도 있다.
package ex02;
public abstract class Animal { // 추상클래스로 만듬
abstract String getName(); // 추상메서드로 만듬
}
package ex02;
/*
Animal 생성(abstract)
타입 일치(다형성) = 쥐(동물), 호랑이(동물)
문지기한테 DIP 만 지켜주면 됨
*/
public class App {
public static void main(String[] args) {
/*
Mouse m1 = new Mouse();
Animal a = m1; 는
Animal a = new Mouse(); 와 같음
*/
Mouse m = new Mouse(); // -> mouse, animal
DoormanProxy doormanProxy = new DoormanProxy(new Doorman());
doormanProxy.쫓아내(m);
}
}
heap 에 animal 와 mouse 가 같이 올라가고,
Mouse m = new Mouse(); 도 되고,
Animal m = new Mouse(); 도 됨

아래는 main 메서드가 있는 App 에서 실행 했을 때, 출력 결과이다.

package ex02;
// 문지기
public class Doorman {
// 동물이면 쫒아내
public void 쫒아내(Animal a){ // OCP
System.out.println(a.getName()+" 쫒아내");
}
}
package ex02;
// 쥐
public class Mouse extends Animal {
private String name = "쥐";
// 재정의됨
public String getName() {
return name;
}
}
package ex02;
public class Tiger extends Animal {
private String name = "호랑이";
public String getName() {
return name;
}
}
package ex02;
// 컴퍼지션(Composition) : has-a
public class DoormanProxy {
private Doorman doorman; // 컴퍼지션
public DoormanProxy(Doorman doorman) {
this.doorman = doorman;
}
public void 쫓아내(Animal a) {
System.out.println("안녕~~~"); // proxy 를 사용, 무조건 들어오면 인사는 한다.
doorman.쫒아내(a);
}
}
이렇게 하면 객체 지향 원칙 중 OCP(Open-Closed Principle) 개방-폐쇄 원칙을 지킬 수 있다.
기존 코드에 손대지 않고 새 코드를 만들 수 있게 된다.
스프링에서 AOP(Aspect-Oriented Programming, 관점 지향 프로그래밍) 기능을 구현할 때, 프록시 객체를 만들어서 실제 객체의 동작을 감싸거나 대리하는 방식으로 기능을 추가한다.
아래의 다른 예시를 보자.

위의 파란 동그라미는 라우터(router)는 분배기 같은 것으로, 네트워크에서 데이터 패킷을 목적지까지 전달하는 장치 또는 소프트웨어이다.
중국에 있는 데이터 a 는 미국의 유튜브 서버로 가기 위해 가장 가까운 라우터를 찾아(?) 타고 타고 Forward Proxy 를 통해 빠져나와 유튜브 서버에 닿게 된다.
출발지에서는 Forward Proxy 를 통해서 빠져나갈 수 있고,
Proxy 를 통해 들어올 때, Reverse Proxy 에서 들어오는 IP 를 차단 시킬 수 있다. ex. 북한 IP 를 들어오지 못하게 입구에서 막아버리는 것이다.
단, 유튜브에서 중국으로부터 들어오는 IP 를 차단하더라도 중간에 인도를 끼워서 IP 를 치환시켜버리면 들어갈 수 있다.
2. 프록시 패턴을 사용하는 이유
우리가 프록시 패턴을 사용 하는 이유는 기존에 있는 애들을 건드리지 않으려고 사용 하는 것이다.
위에서 봤던 예제를 다시 보자.
2-1. DoormanProxy (Open)
package ex02;
// 컴퍼지션(Composition) : has-a
public class DoormanProxy {
private Doorman doorman; // doorman 은 기존에 있던 클래스
public DoormanProxy(Doorman doorman) {
this.doorman = doorman;
}
public void 쫓아내(Animal a) {
System.out.println("안녕~~~");
doorman.쫒아내(a);
}
}
2-2. 기존에 있던 클래스 전체 (Close)
// DoormanProxy 제외 클래스 전체, 위와 상동
기존에 있는 doorman 클래스를 건드리지 않게 doormanProxy 로 감싸고 있음.
package ex02;
/*
Animal 생성(abstract)
타입 일치(다형성) = 쥐(동물), 호랑이(동물)
문지기한테 DIP 만 지켜주면 됨
*/
public class App {
public static void main(String[] args) {
/*
Mouse m1 = new Mouse();
Animal a = m1; 는
Animal a = new Mouse(); 와 같음
*/
Mouse m = new Mouse(); // -> mouse, animal
DoormanProxy doormanProxy = new DoormanProxy(new Doorman());
doormanProxy.쫓아내(m);
}
}
3. 정리
스프링 프레임워크의 AOP(Aspect-Oriented Programming 관점 지향 프로그래밍) 는
Proxy 를 사용하여, 프로그래머가 핵심 로직만 짤 수 있게 해준다.
내가 핵심 로직에만 집중 할 수 있게 해주는 것.
코드를 깔끔하게 만들 수 있음.
만들어져 있는 proxy 패턴을 보면 기존에 있는 클래스에 부가 기능이 들어가야 하는구나, 추가되는게 있겠구나하고 예상 할 수 있겠다.
Share article