본문 바로가기
Spring-Proxy, AOP

Spring - Proxy

by suhsein 2024. 11. 15.
728x90

인프런 김영한 강사님 강의를 듣고 정리한 내용입니다.

프록시

Proxy는 대리자라는 뜻으로 말 그대로 진짜 객체 대신 대리로 역할을 수행해주는 객체를 일컫는다.
일반적으로 서비스를 요청하는 쪽을 클라이언트, 처리하여 응답하는 쪽을 서버라고 한다. 프록시는 클라이언트가 서버에게 요청을 할 때, 중간에서 요청을 가로채어 수행하게 된다.
클라이언트의 호출에서 서버가 요청을 직접 수행하는 것을 직접 호출, 프록시가 서버 대신 요청을 수행하는 것을 간접 호출이라고 한다.

프록시의 주요 기능

1. 접근 제어 : Proxy Pattern

  • 권한에 따른 접근 차단
  • 캐싱
  • 지연 로딩

처음 진짜 객체를 호출한 후에, 변하지 않는 데이터에 대해서 캐싱을 한다. 그리고 다음 번에 같은 요청이 들어오면 객체를 호출하는 대신 프록시가 캐싱해둔 데이터를 반환한다. 캐싱을 통해 속도를 높일 수 있다.

접근 제어와 관련하여 프록시를 사용하는 것을 GoF에서 프록시 패턴이라고 부른다.

2. 부가 기능 추가 : Decorator Pattern

  • 원래 서버가 제공하는 기능에 더해서 부가 기능을 수행한다.
  • 예) 요청 값이나, 응답 값을 중간에 변형한다.
  • 예) 실행 시간을 측정해서 추가 로그를 남긴다.

여러 객체 간의 중복되는 로직을 수행하는 경우, 혹은 해당 클래스의 비즈니스 로직과 상관없는 부가적인 기능을 추가하는 경우에도 프록시를 사용할 수 있다. 프록시의 호출 메서드에서 부가 기능과 관련한 로직을 작성하고, 중간에 진짜 객체의 메서드를 호출하는 방식으로 구성할 수 있다.

부가 기능 추가(기능 확장)와 관련하여 프록시를 사용하는 것을 GoF에서 데코레이터 패턴이라고 부른다.

프록시 패턴과 데코레이터 패턴은 모두 프록시를 사용하는 디자인 패턴이지만, 위에서 설명했던 의도에 따라서 둘을 구분한다.

프록시를 만드는 방법

대체 가능

프록시가 요청을 수행하려면, 클라이언트가 요청을 할 때 서버에게 요청을 한 것인지, 프록시에게 요청을 한 것인지 구분할 수 없어야한다.
그러려면 프록시는 진짜 객체의 클래스를 상속해야한다. 즉, 프록시는 진짜 객체의 클래스에 의존한다.

쉽게 이야기 해서 서버와 프록시는 같은 인터페이스를 사용해야 한다. (구체 클래스를 기반으로 한 다형성으로 프록시를 생성할 수도 있다.) 그리고 클라이언트가 사용하는 서버 객체를 프록시 객체로 변경해도 클라이언트 코드를 변경하지 않고 동작할 수 있어야 한다.

클래스 의존 관계

런타임 의존 관계 (프록시 도입 X)

런타임에 클라이언트 코드에 서버와 관련하여 의존 관계가 주입된다. 프록시를 도입하지 않으면 서버 객체가 주입된다.

런타임 의존 관계 (프록시 도입 O)

프록시를 도입할 경우, 서버 객체 대신 서버를 상속하는 프록시 객체가 클라이언트 코드에 대신 주입된다.

상속을 이용한 DI로 클라이언트 코드의 변경 없이 유연하게 프록시를 주입할 수 있다.

프록시 클래스 구성

프록시 클래스를 구성하는 전반적인 과정은 이렇다.

  1. 원본 클래스를 상속하는 프록시 클래스 생성
  2. 원본 객체를 저장하는 필드 선언
  3. 원본 객체를 주입받을 수 있도록 한다(ex. 생성자 주입)
  4. 로직 작성(접근 제어 / 기능 확장)

그리고 Configuration 클래스를 통해서 빈을 수동 등록할 때 원본 객체 대신에 프록시 객체를 리턴하도록 하면 된다.

하지만 이 방법에는 문제점이 있다. 여러 클래스가 같은 접근 제어 혹은 부가 기능을 이용하고자 할 때, 모든 클래스의 프록시 클래스를 생성해야한다는 것이다.
이러한 문제를 해결하기 위해서 동적 프록시 기술을 사용할 수 있다.

728x90