Proxy란 (with Java)

이우길·2022년 3월 12일
0

Back To Java

목록 보기
3/4
post-thumbnail

Proxy패턴에 대하여...(with Java)

두 편에 걸쳐 Proxy, Dynamic Proxy 대하여 stydy 및 정리를 하려 한다.

proxy라는 기술은 전반적으로 여러 곳에서 사용되지만 앞으로 작성할 2개의 글은 code(Java)에서 Proxy가 어떻게 사용되는지 알아보고자 한다.


Goal

앞으로 더 깊게 학습할 Spring, JPA 등에 내부적인 기능에 대한 이해를 돕기 위한 Proxy 개념 Study


Proxy란?

Java에서 Proxy는 이전에 다뤘던 Reflection과 연결된다. (이전 글 Reflection이란 참조)

Proxy란 사전적으로는 대리인이라는 뜻을 가지고 있다. Java에서 프록시는 RealSubject는 자신의 기능에만 집중을 하고 그 이외 부가 기능을 제공하거나 접근을 제어하는 역할을 Proxy 객체에게 위임한다.

이로 인해 SOLID원칙 중 SRP를 지향하는 코드로 작성이 가능해진다.

Proxy 패턴은 아래와 같은 구조를 가지고 있는데 Client는 Interface type의 Subject를 의존하고 있고 해당 Interface를 Proxy와 RealSubject가 구현을 하고 있다.

프록시 Pattern의 특징의 특징은 다음과 같다.

  • 프록시 객체는 RealSubject와 같은 이름의 메서드를 구현한다. (interface를 구현)

  • 프록시 객체는 RealSubject에 대한 참조 변수를 가진다.

  • 프록시 객체는 RealSubject의 method를 호출하고 그 결과를 클라이언트에게 반환한다.

  • 프록시 객체는 RealSubject 메서드의 호출 전, 후에 별도의 로직을 수행할 수 있다.


예제 코드 (Pure java)

먼저 Client가 호출 할 Interface를 정의한다.

// interface
public interface BookService {
    void printTitle(Book book);
}

Interface를 구현하고 있는 RealSubject를 정의한다.

// RealSubject
public class BookServiceImpl implements BookService{
    @Override
    public void printTitle(Book book) {
        System.out.println("book.getTitle() = " + book.getTitle());
    }
}

Interface를 구현하며 RealSubject를 참조하고 있는 Proxy객체를 정의한다.

이 때 Proxy안에서 만은 작업들을 할 수 있지만 간단한 logging을 남기는 작업을 진행하겠다.

// proxy
public class BookServiceImplProxy implements BookService{

    BookService bookService = new BookServiceImpl();

    @Override
    public void printTitle(Book book) {
        System.out.println("prev prev method");
        bookService.printTitle(book);
        System.out.println("prev after method");
    }
}

이 후 BookService의 인스턴스를 생성 할 때 BookServiceImplProxy와 같은 Proxy객체를 넣어준 후 Client는 해당 Interface를 사용하게 된다.

// main
public static void main(String[] args) {
    BookService BookService = new BookServiceImplProxy();
    bookServiceImplProxy.printTitle(new Book("foobar"));

    // output
    // prev prev method
    // book.getTitle() = foobar
    // prev after method
}

proxy 패턴을 이용할 때 고려해야 할 점들...

위의 예제 코드와 같이 Proxy 객체를 직접 생성하는 일은 많은 불편함을 가져다 준다. (Proxy를 적용하려는 interface의 method가 1개라면 괜찮을 수도 있겠지만?)

target이 여러개이고 대부분 동일한 기능을 제공해야 하는 Proxy를 정의해야 한다면? 중복 코드는 무척이나 발생할 것이며 생성성도 떨어 질 것이다.

이러한 점들을 이 후 알아볼 Dynamic Proxy라는 개념을 통해 개선해나가보도록 하자! (Java Reflection package에서 제공 -> Dynamic Proxy도 Reflection의 연장선의 개념이다.)


마무리

ProxyRealSubject의 대리자와 같은 역할을 하며 Client가 interface를 사용할 때 구현체로 RealSubject가 아닌 Proxy를 사용한다.

Proxy기능을 사용함으로 RealSubject에 부가 기능을 추가하지 않고 Proxy에 접근 제어나 부가 기능들을 추가하여 SOLID (SRP)원칙을 지향하는 코드를 짤 수 있다.

Java에서 Proxy객체를 직접 구현하고 작성할 수 있지만 번거롭고 이 후 확장을 할 때 많은 제약조건 및 중복 코드가 생길 수 도 있다. -> 이 것을 개선하고자 dynamic proxy라는 기술을 도입!


참조

https://www.inflearn.com/course/the-java-code-manipulation/dashboard

https://limkydev.tistory.com/79

profile
leewoooo

0개의 댓글