본문 바로가기

카테고리 없음

[Spring] 디자인 패턴 - 프록시 패턴 예시

참고 1. 스프링-핵심-원리-고급편, 김영한
참고 2. 위키백과

 

아래는 캐시 서버 형태의 프록시 예시 코드이다.

1. 인터페이스를 만들기

아래 사진과 같이 프록시와 실제 서버는 같은 인터페이스를 상속받는다. 따라서, 먼저 가장 큰 틀이 되는 서버 인터페이스를 만들어야 한다.

의존 관계

아래와 같이 인터페이스를 만들어 준다. 이후, 프록시와 실제 클래스에서는 Operation을 상속받아 기능을 구현할 것이다. 

public interface Subject {
    String operation();
}

2. 실제 클래스와 프록시 만들기

실제 클래스

아래는 실제 서버 클래스이다. 간단히 로그를 출력하고 1초간 정지한다.

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class RealSubject implements Subject{
    @Override
    public String operation() {
        log.info("실제 객체 호출");
        sleep(1000);
        return "data";
    }

    private void sleep(int millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

캐시 프록시 

아래는 캐시형태의 프록시이다. 서버 인터페이스를 상속받아 구현하며, 이후 위 실제 클래스를 생성자 주입으로 받게 된다. 그리고 실제 클래스가 동작 후 해당 결과 값을 내부에 저장 후 이를 캐시로 사용한다. 

@Slf4j
public class CacheProxy implements Subject{

    private Subject target;
    private String cacheValue;

    public CacheProxy(Subject subject) {
        this.target = subject;
    }

    @Override
    public String operation() {
        log.info("프록시 호출");
        if (cacheValue == null) {
            cacheValue = target.operation();
        }
        return cacheValue;
    }
}

3. 클라이언트

이제 위에서 만든 Subject(Server Instance) 혹은 CacheProxy의 operation을 실행하기 위한 클라이언트를 아래와 같이 정의해야 한다. 클라언트는 실제 서버 객체 혹은 프록시를 생성자로 주입받고, operation을 실행한다. 

public class Client {

    private Subject subject;

    public Client(Subject subject) {
        this.subject = subject;
    }

    public void execute() {
        subject.operation();
    }
}

사용 예시

아래 2번째 테스트 코드와 같이 중간에 프록시를 거치게 되면, 프록시에 정의한 접근제어가 추가 된다. (아래의 CacheProxy는 최초 1회만 실제 서버 객체의 함수를 호출한다.)

@Test
void noProxyTest() {
    RealSubject realSubject = new RealSubject();
    Client client = new Client(realSubject);

    client.execute();
    client.execute();
    client.execute();

}

@Test
void ProxyTest() {
    RealSubject realSubject = new RealSubject();
    CacheProxy cacheProxy = new CacheProxy(realSubject);
    Client client = new Client(cacheProxy);

    client.execute();
    client.execute();
    client.execute();

}