본문 바로가기
기술면접/디자인 패턴

[디자인 패턴] 프록시 패턴이란?

by illlilillil 2022. 3. 22.
  • 프록시 패턴이란??? 
    • Proxy는 대리자라는 의미를 갖고 있다.
    • 비서를 거쳐 사장과 커뮤니케이션하는 개념
    • 객체 사용을 위해 직접 참조하지 않고, 해당 객체를 바라보는 객체를 생성해 실제 객체의 생성을 미룬다.
    • 프록시 사용 이유는?
      • 객체 지향의 원칙인 OCP(Open-Closed Principle)을 지키기 위해서이다.
      • 자기 자신에 대한 수정에는 열려 있고 외부의 접근에 대해서는 닫혀 있어야 한다는 원칙
    • 프록시 패턴의 장점
      • 객체 생성 전에도 프록시를 통해 참조가 가능하다.
      • 실제 객체의 public, protected를 숨길 수 있다.(인터페이스로 대체)
      • 실제 객체에 대한 사전 처리가 가능하다.
    • 프록시 패턴의 단점
      • 자주 사용될 경우, 가짜 객체가 생성되는 것이기에 성능 저하가 발생할 수 있다.
      • 로직이 복잡해져 가독성이 떨어질 수 있다.
    • 프록시 패턴의 종류
      • 가상 프록시 - 필요 시점까지 객체 생성 연기하지만 참조를 통해 객체를 이용할 수 있다.
      • 원격 프록시 - 클라우드 환경의 Google Docs의 동작 원리처럼, 다른 주소 공간에 있는 객체를 프록시가 참조하도록 해 마치 같은 공간에 있는 것처럼 동작하게 한다.
      • 보호 프록시 - 실제 객체에 대한 접근 제어를 위해 사용하는 패턴

프록시 구현 예제

영화라는 객체를 두고 그 안의 변수로 story라는 것을 두었습니다.

public interface Movie {
    void displayStory();
}
public class Real_Movie implements Movie {
    private String story;

    public Real_Movie(String story) {
        this.story=story;
        loadFromMemory();
    }

    private void loadFromMemory() {
        System.out.println("story = " + story);
    }

    @Override
    public void displayStory() {
        System.out.println("실제 정보: "+ story);
    }
}
public class Proxy_Movie implements Movie {
    private String story;
    private Real_Movie real_movie;

    public Proxy_Movie(String story) {
        this.story=story;
    }

    @Override
    public void displayStory() {
        //실제 객체가 비어 있다면 데이터 주입
        if(real_movie==null) {
            real_movie = new Real_Movie(story);
        }
        real_movie.displayStory();
    }
}
public class Proxy {
    public static void main(String[] args) {
        Movie movie1 = new Proxy_Movie("영화:명량");
        Movie movie2 = new Proxy_Movie("영화:스파이더맨");

        movie1.displayStory();
        System.out.println();
        movie2.displayStory();
    }
}

아래 결과물과 같이 Proxy 메서드에서는 직접적으로 Real_Movie에 접근하지 않고도 프록시를 통해 메서드를 호출할 수 있습니다.

스프링에서의 프록시 패턴 활용

  1. Transaction
    • 위 어노테이션에 프록시가 활용된다.
    • 프록시를 통해 create 메소드의 원자성을 보장해준다.
    @Service
    public class BookManager {
        
        @Autowired
        private BookRepository repository;
    
        @Transactional
        public Book create(String author) {
            System.out.println(repository.getClass().getName());
            return repository.create(author);
        }
    }
  2. AOP(Aspect Oriented Programming) - 관점을 추출해 모듈화하는 기술
    1. 프록시 패턴을 구체화하는 기술
      1. JDK Proxy
      2. CGLib
    2. JDK Proxy
      • 인터페이스를 기반으로 동적으로 프록시를 생성해준다.
      • InvocationHandler라는 인터페이스 제공
      • 인터페이스가 기반이기 때문에 인터페이스가 필수
      • 리플렉션 사용
        • 리플렉션은 클래스의 구체적인 타입을 몰라도 접근 가능하게 하는 API
    3. CGLIB
      • JDK Proxy는 인터페이스가 필수라는 단점을 개선하고 상속으로 해결한다.
      • CGLIB은 그 부분을 개선해 구체 클래스만 있어도 동적 프록시를 생성
      • MethodInterceptor 인터페이스 제공
      • 제약 사항
        • 부모 클래스의 기본 생성자가 있어야 한다.(@NoArgsConstructor)
        • 메서드나 클래스에 final이 붙으면 상속이나 오버라이딩이 불가능
    4. 프록시 팩토리
      1. 위 두 기술의 혼합 사용을 위해 도입
      2. 인터페이스 유무에 따라 프록시 기술 선택
  3. 지연 로딩
    1. 지연 로딩에도 프록시 기술이 사용된다. 즉시로딩은 프록시를 사용하지 않는다.
    2. 데이터 조회시 기본 동작
      1. 데이터 요청
      2. 멤버 객체를 타겟으로 하는 멤버 프록시가 초기화된다(처음 사용시)
      3. 영속성 컨텍스트에 이미 있다면 멤버 객체 반환
      4. 없다면 DB 조회 및 멤버 객체 생성 후 반환

[추가 공부할 사항]

AOP 개념

위빙

트랜잭션 동작 원리

Spring cache @Cacheable method ignored when called from within the same class

[참고 문헌]

[Design Pattern] 프록시 패턴(Proxy Pattern)에 대하여

Spring의 디자인 패턴들

[Spring] AOP 2. 동적 프록시와 스프링이 지원하는 프록시

 

[Spring] @Transactional 사용시 주의해야할 점

'기술면접 > 디자인 패턴' 카테고리의 다른 글

[디자인 패턴] 커맨드 패턴  (0) 2022.04.05
[디자인 패턴] 전략 패턴  (0) 2022.04.05
[디자인 패턴] 싱글톤 패턴  (0) 2022.04.01

댓글