본문 바로가기
디자인 패턴

프록시 패턴(Proxy Pattern)

by mjjang 2022. 3. 7.

프록시는 대리인이라는 뜻으로 프록시 패턴은 클라이언트가 객체를 직접 참조하는 것이 아니라 proxy(대리인)를 통해 객체에 접근하는 패턴입니다.

구조와 글만 보면 이해하기 어려우니 예제를 통해 자세히 알아보겠습니다.

public class Company {

    public void enter() {
        System.out.println("들어 가기");
    }
}

해당 코드에서 만약 직원들만 회사에 들어갈 수 있다는 조건이 추가된다면 코드가 어떻게 수정될까요?

public class Company {

    public void enter(String status) {
        if ("employee".equals(status) {
            System.out.println("들어 가기");
        }
    }
}

if문을 추가해서 직원일 경우에만 들어가게 코드를 수정할 수 있습니다. 하지만 이런 식으로 수정하면 enter() 라는 메서드가 인증 기능까지 수행하게 되고 메서드의 변경 포인트가 증가하게 됩니다. 이럴 때 proxy를 사용하면 기존에 코드를 수정하지 않고 새로운 기능을 추가할 수 있습니다.

public enum Status {

    EMPLOYEE, GUEST
}

public interface Company {

    void enter(Status status);
}

public class MyCompany implements Company {

    @Override
    public void enter(Status status) {
        System.out.println(status + "들어가기");
    }
}

EMPLOYEE, GUEST라는 enum을 추가하고 Company 인터페이스를 구현한 MyCompany 클래스를 만들었습니다.

@RequiredArgsConstructor
public class CompanyProxy implements Company {

    private final Company company;

    @Override
    public void enter(Status status) {
        if (Status.GUEST == status) {
            throw new IllegalArgumentException("손님은 들어갈 수 없습니다.");
        }
        company.enter(status);
    }
}

그리고 Company 인터페이스를 구현한 CompanyProxy 클래스를 만들었습니다. 멤버 변수로는 Company 타입을 가지고 있습니다. proxy객체에서 인증을 처리하고 company.enter(status)를 호출하는 것을 확인할 수 있습니다. 즉 객체에 직접 접근하지 않고 proxy를 통해 접근해서 기존 코드를 수정하지 않고 새로운 기능을 proxy에 위임했습니다.

Proxy를 테스트해 보겠습니다.

class ProxyTest {

    @Test
    public void enter() {
        // given
        Company myCompany = new MyCompany();
        CompanyProxy proxy = new CompanyProxy(myCompany);
        // when
        IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> {
            proxy.enter(Status.GUEST);
        });
        // then
        assertThat(exception.getMessage()).isEqualTo("손님은 들어갈 수 없습니다.");
    }
}

CompanyProxy를 생성할 때 실제 기능을 수행하는 myCompany 인스턴스를 넘겨줍니다.
클라이언트에서는 proxy를 통해 enter 메서드를 수행합니다.

즉, 클라이언트 → myCompany를 호출하는 것이 아닌 중간에 proxy를 두어서

클라이언트 → proxy(인증) → myCompany(출입) 기존에 코드를 수정하지 않고 인증을 proxy에서 처리하게 하여 SRP를 지킬 수 있게 됩니다.
프록시는 인증뿐만 아니라 초기화 지연, 접근 제어, 로깅, 캐싱 등 다양하게 응용이 가능합니다.

마지막으로 프록시 패턴의 장단점을 설명하고 포스팅을 마치겠습니다.

장점

  • 기존 코드를 수정하지 않고 사용할 수 있다.
  • 기존 코드가 해야 하는 일만 할 수 있다. (SRP)
  • 기능 추가 및 초기화 지연 등으로 다양하게 활용할 수 있다.

단점

  • 코드의 복잡도가 증가한다.

댓글