You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
LogTrace 가 아직 스프링 빈으로 등록되어 있지 않은데, 이 부분은 바로 다음에 등록할 것이다.
V1 프록시 런타임 객체 의존 관계 설정
이제 프록시의 런타임 객체 의존 관계를 설정하면 된다. 기존에는 스프링 빈이 orderControlerV1Impl , orderServiceV1Impl 같은 실제 객체를 반환했다. 하지만 이제는 프록시를 사용해야한다. 따라서 프록시를 생성하고 프록시를 실제 스프링 빈 대신 등록한다. 실제 객체는 스프링 빈으로 등록하지 않는다.
프록시는 내부에 실제 객체를 참조하고 있다. 예를 들어서 OrderServiceInterfaceProxy 는 내부에 실제 대상 객체인 OrderServiceV1Impl 을 가지고 있다.
정리하면 다음과 같은 의존 관계를 가지고 있다.
proxy -> target
orderServiceInterfaceProxy -> orderServiceV1Impl
스프링 빈으로 실제 객체 대신에 프록시 객체를 등록했기 때문에 앞으로 스프링 빈을 주입 받으면 실제 객체 대신에 프록시 객체가 주입된다.
실제 객체가 스프링 빈으로 등록되지 않는다고 해서 사라지는 것은 아니다. 프록시 객체가 실제 객체를 참조하기 때문에 프록시를 통해서 실제 객체를 호출할 수 있다. 쉽게 이야기해서 프록시 객체 안에 실제 객체가 있는 것이다.
이제 스프링빈에 등록된 컨트롤러는 프록시
요청이 컨트롤러 프록시에 들어오면, 프록시에 있는 로깅 기능 호출
이후에 프록시의 타겟을 호출, 타겟은 OrderService를 호출
우리는 컨피그에서 OrderService 에 프록시를 넣음, 프록시에 있는 로깅 기능 호출
이후에 프록시의 타겟을 호출, 타겟은 OrderRepository 를 호출
우리는 컨피그에서 OrderRepository 에 프록시를 넣음, 프록시에 있는 로깅 기능 호출
정리
추가된 요구사항을 다시 확인해보자. 추가된 요구사항
원본 코드를 전혀 수정하지 않고, 로그 추적기를 적용해라.
특정 메서드는 로그를 출력하지 않는 기능
보안상 일부는 로그를 출력하면 안된다.
다음과 같은 다양한 케이스에 적용할 수 있어야 한다.
v1 - 인터페이스가 있는 구현 클래스에 적용
v2 - 인터페이스가 없는 구체 클래스에 적용
v3 - 컴포넌트 스캔 대상에 기능 적용
프록시와 DI 덕분에 원본 코드를 전혀 수정하지 않고, 로그 추적기를 도입할 수 있었다. 물론 너무 많은 프록시 클래스를 만들어야 하는 단점이 있기는 하다. 이 부분은 나중에 해결하기로 하고, 우선은 v2 - 인터페이스가 없는 구체 클래스에 프록시를 어떻게 적용할 수 있는지 알아보자.
인터페이스가 없어도 프록시 사용할 수 있음, 왜냐면 자바의 다형성은 인터페이스든, 클래스든 다 사용할 수 있기 때문
구체 클래스 기반 프록시 - 예제1
다음에 보이는 ConcreteLogic 은 인터페이스가 없고 구체 클래스만 있다. 이렇게 인터페이스가 없어도 프록시를 적용할 수 있을까?
먼저 프록시를 도입하기 전에 기본 코드를 작성해보자.
지금까지 인터페이스를 기반으로 프록시를 도입했다. 그런데 자바의 다형성은 인터페이스를 구현하든, 아니면 클래스를 상속하든 상위 타입만 맞으면 다형성이 적용된다. 쉽게 이야기해서 인터페이스가 없어도 프록시를 만들수 있다는 뜻이다. 그래서 이번에는 인터페이스가 아니라 클래스를 기반으로 상속을 받아서 프록시를 만들어보겠다.
여기서 핵심은 ConcreteClient 의 생성자에 concreteLogic 이 아니라 timeProxy 를 주입하는 부분이다. ConcreteClient 는 ConcreteLogic 을 의존하는데, 다형성에 의해 ConcreteLogic 에 concreteLogic 도 들어갈 수 있고, timeProxy 도 들어갈 수 있다.
ConcreteLogic에 할당할 수 있는 객체 ConcreteLogic = concreteLogic (본인과 같은 타입을 할당) ConcreteLogic = timeProxy (자식 타입을 할당)
실행 결과
실행 결과를 보면 인터페이스가 없어도 클래스 기반의 프록시가 잘 적용된 것을 확인할 수 있다.
참고: 자바 언어에서 다형성은 인터페이스나 클래스를 구분하지 않고 모두 적용된다. 해당 타입과 그 타입의 하위 타입은 모두 다형성의 대상이 된다. 자바 언어의 너무 기본적인 내용을 이야기했지만, 인터페이스가 없어도 프록시가 가능하다는 것을 확실하게 깊고 넘어갈 필요가 있어서 자세히 설명했다.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
인터페이스 기반 프록시 - 적용
인터페이스와 구현체가 있는 V1 App에 지금까지 학습한 프록시를 도입해서
LogTrace를 사용해보자.프록시를 사용하면 기존 코드를 전혀 수정하지 않고 로그 추적 기능을 도입할 수 있다.
이게 중요하다. 인터페이스를 의존해야 이걸 프록시로 바꿔치기 할 수 있음!
여기에 로그 추적용 프록시를 추가하면 다음과 같다.
Controller,Service,Repository각각 인터페이스에 맞는 프록시 구현체를 추가한다.그리고 애플리케이션 실행 시점에 프록시를 사용하도록 의존 관계를 설정해주어야 한다. 이 부분은 빈을 등록하는 설정 파일을 활용하면 된다.
부가기능 로직이 다 프록시에 들어가있음!
noLog() 메서드는 로그를 남기지 않아야 한다. 따라서 별도의 로직 없이 단순히
target을 호출하면 된다.빈등록에서 구현체를 반환하는게 아니라 프록시를 반환해야한다!
LogTrace가 아직 스프링 빈으로 등록되어 있지 않은데, 이 부분은 바로 다음에 등록할 것이다.V1 프록시 런타임 객체 의존 관계 설정
이제 프록시의 런타임 객체 의존 관계를 설정하면 된다. 기존에는 스프링 빈이
orderControlerV1Impl,orderServiceV1Impl같은 실제 객체를 반환했다. 하지만 이제는 프록시를 사용해야한다. 따라서 프록시를 생성하고 프록시를 실제 스프링 빈 대신 등록한다. 실제 객체는 스프링 빈으로 등록하지 않는다.OrderServiceInterfaceProxy는 내부에 실제 대상 객체인OrderServiceV1Impl을 가지고 있다.proxy -> targetorderServiceInterfaceProxy -> orderServiceV1ImplAppV1Config를 통해 프록시를 적용하기 전InterfaceProxyConfig를 통해 프록시를 적용한 후최종적으로 이런 런타임 객체 의존관계가 발생한다.
실행해보면 잘 작동하는 것 확인 가능
이제 스프링빈에 등록된 컨트롤러는 프록시
요청이 컨트롤러 프록시에 들어오면, 프록시에 있는 로깅 기능 호출
이후에 프록시의 타겟을 호출, 타겟은
OrderService를 호출우리는 컨피그에서
OrderService에 프록시를 넣음, 프록시에 있는 로깅 기능 호출이후에 프록시의 타겟을 호출, 타겟은
OrderRepository를 호출우리는 컨피그에서
OrderRepository에 프록시를 넣음, 프록시에 있는 로깅 기능 호출정리
추가된 요구사항을 다시 확인해보자.
추가된 요구사항
원본 코드를 전혀 수정하지 않고, 로그 추적기를 적용해라.특정 메서드는 로그를 출력하지 않는 기능보안상 일부는 로그를 출력하면 안된다.v1 - 인터페이스가 있는 구현 클래스에 적용프록시와 DI 덕분에 원본 코드를 전혀 수정하지 않고, 로그 추적기를 도입할 수 있었다. 물론 너무 많은 프록시 클래스를 만들어야 하는 단점이 있기는 하다. 이 부분은 나중에 해결하기로 하고, 우선은 v2 - 인터페이스가 없는 구체 클래스에 프록시를 어떻게 적용할 수 있는지 알아보자.
인터페이스가 없어도 프록시 사용할 수 있음, 왜냐면 자바의 다형성은 인터페이스든, 클래스든 다 사용할 수 있기 때문
구체 클래스 기반 프록시 - 예제1
다음에 보이는
ConcreteLogic은 인터페이스가 없고 구체 클래스만 있다. 이렇게 인터페이스가 없어도 프록시를 적용할 수 있을까?먼저 프록시를 도입하기 전에 기본 코드를 작성해보자.
클라이언트
여기에도 클라이언트 코드 변경 없이 프록시를 적용할 수 있다!
구체 클래스 기반 프록시 - 예제2
클래스 기반 프록시 도입
지금까지 인터페이스를 기반으로 프록시를 도입했다. 그런데 자바의 다형성은 인터페이스를 구현하든, 아니면 클래스를 상속하든 상위 타입만 맞으면 다형성이 적용된다. 쉽게 이야기해서 인터페이스가 없어도 프록시를 만들수 있다는 뜻이다. 그래서 이번에는 인터페이스가 아니라 클래스를 기반으로 상속을 받아서 프록시를 만들어보겠다.
TimeProxy프록시는 시간을 측정하는 부가 기능을 제공한다. 그리고 인터페이스가 아니라 클래스인ConcreteLogic를 상속 받아서 만든다.여기서 핵심은
ConcreteClient의 생성자에concreteLogic이 아니라timeProxy를 주입하는 부분이다.ConcreteClient는ConcreteLogic을 의존하는데, 다형성에 의해ConcreteLogic에concreteLogic도 들어갈 수 있고,timeProxy도 들어갈 수 있다.ConcreteLogic에 할당할 수 있는 객체
ConcreteLogic = concreteLogic(본인과 같은 타입을 할당)ConcreteLogic = timeProxy(자식 타입을 할당)실행 결과

실행 결과를 보면 인터페이스가 없어도 클래스 기반의 프록시가 잘 적용된 것을 확인할 수 있다.
참고: 자바 언어에서 다형성은 인터페이스나 클래스를 구분하지 않고 모두 적용된다. 해당 타입과 그 타입의 하위 타입은 모두 다형성의 대상이 된다. 자바 언어의 너무 기본적인 내용을 이야기했지만, 인터페이스가 없어도 프록시가 가능하다는 것을 확실하게 깊고 넘어갈 필요가 있어서 자세히 설명했다.
Beta Was this translation helpful? Give feedback.
All reactions