-
Spring Core - 인터페이스 기반 프록시(V1)FrameWork/Spring&Spring-boot 2024. 3. 11. 15:28
인터페이스 기반 프록시 - 적용
인터페이스와 구현체가 있는 V1 App에 앞서 학습한 프록시를 도입해서 LogTrace를 사용해보자.
프록시를 사용하면 기존 코드를 전혀 수정하지 않고 로그 추적 기능을 도입할 수 있다.
V1의 App의 기본 클래스 의존 관계와 런타임시 객체 인스턴스 의존 관계는 다음과 같다.
V1 기본 클래스 의존 관계
V1 런타임 객체 의존 관계
여기에 로그 추적용 프록시를 추가하면 다음과 같다.
V1 프록시 의존 관계 추가
Controller , Service , Repository 각각 인터페이스에 맞는 프록시 구현체를 추가한다.(그림에서 Repository는 생략되었다.)
V1프록시 런타임 객체 의존 관계
그리고 애플리케이션 실행 시점에 프록시를 사용하도록 의존 관계를 설정해주어야 한다. 이 부분은 빈을 등록하는 설정 파일을 활용하면 된다.(그림에서 리포지토리는 생략되었다.)
InterfaceProxyConfig
package com.core.springproxy.config.v1_proxy.interface_proxy; import com.core.springproxy.app.v1.*; import com.core.springproxy.trace.logTrace.LogTrace; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class InterfaceProxyConfig { @Bean public OrdersControllerV1 ordersController(LogTrace logTrace){ OrdersControllerV1 controllerImpl = new OrderControllerV1Impl(orderService(logTrace)); return new OrderControllerInterfaceProxy(controllerImpl,logTrace); } @Bean public OrderServiceV1 orderService(LogTrace logTrace){ OrderServiceV1 serviceImpl = new OrderServiceV1Impl(orderRepository(logTrace)); return new OrderServiceInterfaceProxy(serviceImpl,logTrace); } @Bean public OrderRepositoryV1 orderRepository(LogTrace logTrace){ OrderRepositoryV1 repositoryImpl = new OrderRepositortyV1Impl(); return new OrderRepositoryInterfaceProxy(repositoryImpl,logTrace); } }
LogTrace가 아직 스프링 빈으로 등록되어 있지 않았는데, 이 부분은 추후에 등록한다.
V1프록시 런타임 객체 의존 관계 설정
- 이제 프록시의 런타임 객체 의존 관계를 설정하면 된다. 기존에는 스프링 빈이 orderControllerV1Impl, orderServiceV1Impl같은 실제 객체를 반환(스프링 @Bean으로 실제 객체를 등록)했다. 하지만 이제는 프록시를 사용한다. 따라서 프록시 객체 인스턴스를 생성하고 프록시를 실제 스프링 빈 대신 등록한다. 실제 객체는 스프링 빈으로 등록하지 않는다.
- 프록시는 내부에 실제 객체를 참조하고 있다. 예를들어 OrderServiceInterfaceProxy는 내부에 실제 대상 객체인 OrderServiceV1Impl을 가지고 있다.
- 정리면 다음과 같은 의존 관계를 가지고 있다.
- proxy → target
- orderServiceInterfaceProxy → orderServiceV1Impl
- 스프링 빈으로 실제 객체 대신에 프록시 객체를 등록했기 대문에 앞으로 스프링 빈을 주입 받으려 실제 객체 대신에 프록시 객체가 주입된다.
- 실제 객체가 스프링 빈으로 등록되지 않는다고 해서 사라지는 것은 아니다. 프록시 객체가 실제 객체를 참조하기 때문에 프록시를 통해서 실제 객체를 호출할 수 있다. 쉽게이야기 해서 프록시 객체 안에 실제 객체가 있는 것이다.
AppV1config를 통해 프록시를 적용
- 실제 객체가 스프링 빈으로 등록된다. 빈 객체의 마지막에 @x0..라고 해둔 것은 인스턴스라는 뜻이다.
InterfaceProxyCofing를 통해 프록시를 적용한 후
- 스프링 컨테이너에 프록시 객체 인스턴스가 등록된다. 스프링 컨테이너는 이제 실제 객체가 아니라 프록시 객체를 스프링 빈으로 관리한다.
- 이제 실제 객체 인스턴스는 스프링 컨테이너와 상관이 없다. 실제 객체는 프록시 객체를 통해서 참조될 뿐이다.
- 프록시 객체는 스프링 컨테이너가 관리하고 자바 힙 메모리에도 올라간다. 반면에 실제 객체는 자바 힙메모리에 올라가지만 스프링 컨테이너가 관리하지 않는다.
최종적으 위 그림과 같은 런타임 객체 의존관계가 발생한다. (리포지토리는 생략했다.)
실행 결과 - 로그
실행 결과를 확인해보면 로그 추적 기능이 프록시를 통해 잘 동작하는 것을 확인할 수 있다.
정리
추가된 요구사항을 다시 확인해 보자
추가된 요구사항
원본 코드를 수정하지 않고, 로그 추적기를 적용해라특정 메서드는 로그를 출력하지 않는 기능보안상 일부는 로그를 출력하면 안된다.
- 다음과 같은 다양한 케이스에 적용할 수 있어야 한다.
v1 - 인터페이스가 있는 구현 클래스에 적용- v2 - 인터페이스가 없는 구체 클래스에 적용
- v3 - 컴포넌트 스캔 대상에 기능 적용
프록시와 DI 덕분에 원본 코드를 전혀 수정하지 않고, 로그 추적기를 도입할 수 있었다. 물론 너무 많은 프로시 클래스를 만들어야 하는 단점이 존재하긴 한다. 이 부분은 차차 해겨하기로 하고, 우선은 v2 - 인터페이스가 없는 구체 클래스에 프록시를 어떻게 적용할 수 있는지 알아보자.
[출처 - 스프링 핵심원리-고급편, 저 김영한]
스프링 핵심 원리 - 고급편 강의 - 인프런
스프링의 핵심 원리와 고급 기술들을 깊이있게 학습하고, 스프링을 자신있게 사용할 수 있습니다., 핵심 디자인 패턴, 쓰레드 로컬, 스프링 AOP스프링의 3가지 핵심 고급 개념 이해하기 📢 수강
www.inflearn.com
'FrameWork > Spring&Spring-boot' 카테고리의 다른 글
Spring Core - 동적 프록시 (리플렉션) (0) 2024.03.12 Spring Core - 구체 클래스 기반 프록시(예제1, 예제2,적용) (0) 2024.03.12 Spring Core - 데코레이터 패턴 (예제1, 예제2, 예제3) (0) 2024.03.11 Spring Core - 프록시 패턴(예제1,예제2,Cache Proxy) (0) 2024.03.08 Spring Core - 프록시 패턴, 데코레이터 패턴 - 소개(요구사항 추가) (0) 2024.03.08