Proxy Pattern은 특정 객체에 접근하는 것을 제어하는 패턴이다.
특정 객체 코드를 수정하지 않고, 접근하는 방식을 추가할 수 있다. (OCP 준수)
Spring과 JPA을 공부하면서 Proxy라는 단어가 자주 언급되고 있어서, 이론을 먼저 이해하려고 한다.
초기화 지연 로딩, 로깅, 캐싱에 활용되고 있다고 한다.
간략하게 접해보니, 어떤 모듈에 대한 추가적인 처리(로깅, 시간 측정)가 필요할 때 유용할 것 같다.
최근 출시한 Elden Ring을 실행하는 코드가 있다고 해보자.
EldenRing.java
-------------------------------------------------------------------------------------------------------------
package proxypattern.before;
public class EldenRing {
public void startGame() {
System.out.println("Now, Go forth, Become Elden Lord");
}
}
Client.java
-------------------------------------------------------------------------------------------------------------
package proxypattern.before;
public class Client {
public static void main(String[] args) {
EldenRing eldenRing = new EldenRing();
eldenRing.startGame();
}
}
이런 상황에서 2가지 요청사항이 생겼다고 해보자.
이미 구현된 객체에 대해 추가적인 처리를 사용하므로, Proxy Pattern을 적용할 수 있다.

2가지 방법으로 위의 요구사항을 Proxy Pattern으로 구현할 수 있다.
EldenRing class를 상속하는 SteamService를 만들어, 이를 구현할 수 있다.
SteamService.java
-------------------------------------------------------------------------------------------------------------
package proxypattern.after;
public class SteamService extends EldenRing {
@Override
public void startGame() {
System.out.println("Welcome to Steam Service");
System.out.println("Signing in");
super.startGame();
System.out.println("Signing out");
}
}
EldenRing.java
-------------------------------------------------------------------------------------------------------------
package proxypattern.after;
public class EldenRing {
public void startGame() {
System.out.println("Now, Go forth, Become Elden Lord");
}
}
Client.java
-------------------------------------------------------------------------------------------------------------
package proxypattern.after;
public class Client {
public static void main(String[] args) {
EldenRing eldenRing = new SteamService();
eldenRing.startGame();
}
}
OCP 원칙을 준수하여, EldenRing.java 코드 수정없이 요구사항을 구현했다.
하지만 상속을 이용하는 방법은, 두 개 이상의 객체를 다루는 요구사항은 구현할 수 없다.
정석적인 Interface를 활용한 Proxy Pattern이다.
단, 기존의 EldenRing class가 새로운 Interface를 구현하도록 수정해야 한다.
EldenRing은 새로운 Interface의 구현체가 될 것이므로, 구체적인 게임을 추상화할 이름이 필요하다.
새로운 Interface의 이름을 GameService라고 부르자.
GameService.java
-------------------------------------------------------------------------------------------------------------
package proxypattern.after2;
public interface GameService {
void startGame();
}
EldenRing.java
-------------------------------------------------------------------------------------------------------------
package proxypattern.after2;
public class EldenRing implements GameService {
@Override
public void startGame() {
System.out.println("Now, Go forth, Become Elden Lord");
}
}
SteamService.java
-------------------------------------------------------------------------------------------------------------
package proxypattern.after2;
public class SteamService implements GameService {
private GameService gameService;
public SteamService(GameService gameService) {
this.gameService = gameService;
}
@Override
public void startGame() {
System.out.println("Welcome to Steam Service");
System.out.println("Signing in");
gameService.startGame();
System.out.println("Signing out");
}
}
Client.java
-------------------------------------------------------------------------------------------------------------
package proxypattern.after2;
public class Client {
public static void main(String[] args) {
GameService gameService = new SteamService(new EldenRing());
gameService.startGame();
}
}
기존 EldenRing code를 추상화하는 Interface를 만들고, 약간의 수정을 거쳐 Proxy Pattern을 구현했다.
Implemation을 사용했기에, GameService 이외 다른 객체에 대해 추가적인 처리가 필요할 때 확장하여 구현할 수 있다.