본문 바로가기

개발&컴퓨터/개발강좌

스프링(Spring) 프레임워크 기본 개념 강좌 (6) - Dynamic Proxy

반응형

6) Dynamic Proxy (동적 프록시)

 

앞선 강좌에서 설명한 대로, AOP를 구현하기 위해 사용되는 프록시(Poxy) 개념은 상당히 유용한 면이 있지만, 단점도 가지고 있음.

 

* 프록시의 단점.

 

 1. 매 번 새로운 클래스 정의 필요.

  - 실제 프록시 클래스(Proxy Class)는 실제 구현 클래스와 동일한 형태를 가지고 있기 때문에 구현 클래스의 Interface를 모두 구현해야 함.

 

 2. 타깃의 인터페이스를 구현하고 위임하는 코드 작성의 번거로움.

  - 부가기능이 필요없는 메소드도 구현해서 타깃으로 위임하는 코드를 일일이 만들어줘야 함.

  - 복잡하진 않지만 인터페이스의 메소드가 많아지고 다양해지면 상당히 부담스러운 작업이 될 수 있음.

  - 타깃 인터페이스의 메소드가 추가되거나 변경될 때마다 함께 수정해줘야 한다는 부담도 있음.

 

 3. 부가기능 코드의 중복 가능성.

  - 프록시를 활용할 만한 부가기능, 접근제어 기능 등은 일반적으로 자주 활용되는 것들이 많기 때문에 다양한 타깃 클래스와 메소드에 중복되어 나타날 가능성이 높음. (특히 트랜잭션(Transaction) 처리는 데이터베이스를 사용하는 대부분의 로직에서 적용되어야 할 필요가 있음.)

  - 메서드가 많아지고 트랜잭션 적용의 비율이 높아지면 트랜잭션 기능을 제공하는 유사한 코드가 여러 메서드에 중복돼서 나타날 수 있음.

 

 

* 해결책은?

 - 다이내믹 프록시(Dynamic Prox)를 이용하는 것! (JDK Dynamic Proxy)

 

 - 다이내믹 프록시란?

    > 런타임 시 동적으로 만들어지는 오브젝트
    > 리플렉션 기능을 이용해서 프록시 생성 (java.lang.reflect)
    > 타깃 인터페이스와 동일한 형태로 생성.
    > 팩토리빈(FactoryBean)을 통해서 생성.

 

  @ 스프링의 빈은 기본적으로 클래스 이름(Class name)과 프로퍼티(Property)로 정의. 
  @ 스프링은 지정된 클래스 이름을 가지고 리플렉션을 이용해서 해당 클래스의 오브젝트를 생성.

 

참고로 스프링은 지정된 클래스 이름을 가지고 리플렉션을 이용하여 해당 클래스의 오브젝트를 생성함.

이 외에도 팩토리빈(FactoryBean)과 프록시 팩토리빈(Proxy FactoryBean)을 통해 오브젝트를 생성할 수 있음. 팩토리빈 이란 스프링을 대신해서 오브젝트의 생성 로직을 담당하도록 만들어진 특별한 빈을 뜻함.

 

[추가 정리]

데코레이터(Decorator) 또는 프록시 패턴(Proxy Pattern)을 적용하는 데에 따른 어려움은 부가기능을 구현할 클래스가 부가기능과 관계없는 메서드들도 인터페이스에 선언된 메서드라면 전부 구현해야 하는 번거로움과 부가기능과 관계된 메소드들에 구현되는 코드 중복을 들 수 있음.

 

 -> 이는 자바의 리플렉션(Reflection)에서 제공하는 다이내믹 프록시(Dynamic Proxy)를 활용하여 해결할 수 있음.

 

1. Proxy.newProxyInstance() 를 통한 프록시 생성.

2. Proxy.newProxyInstance() 를 호출할 때 전달하는 InvocationHandler 인터페이스의 단일 메소드인 invoke()에 부가 기능을 단 한번 만 구현함으로써 코드 중복 해결.


=> 다이나믹 프록시 오브젝트는 클래스 파일 자체가 존재하지 않음.

=> 빈 오브젝트로 등록 불가.

=> 팩토리빈 인터페이스 활용. (팩토리빈 인터페이스를 구현한 클래스를 빈으로 등록)

 

 

반응형