7. AOP 프로그래밍 #2 프록시(Proxy)와 AOP

2021. 7. 27. 15:44JAVA/Spring

본 글은 초보 웹 개발자를 위한 스프링5 프로그래밍 입문 도서의 내용을 복습하기 위해 작성된 글입니다.

7.2 프록시와 AOP

팩토리얼 메소드의 수행시간을 알고 싶다고 가정하자. 쉬운 방법은 메소드의 시작과 끝에서 시간을 구하고 이 두시간의 차이를 출력하는 것이다. 예를 들어 아래의 ImpleCalculator 클래스를 다음과 같이 수정하면 된다.

 

팩토리얼 메소드에서 수행시간을 출력하는 기능을 추가한 예제

public class ImpleCalculator implements Calculator{

	@Override
	public long factorial(long num) {
    	long start = System.currentTimeMillis();
		long result  = 1;
		for(long i=1; i<=num;i++)
		{
			result *= i;
		}
        long end = System.currentTimeMillis();
        System.out.printf("ImpleCalculator.factorial(%d) 실행 시간 = %d\n", num, (end-start));
		return result;
	}
	
}

 

재귀적으로 팩토리얼을 구현한 메서드같은 경우 실행 시간의 출력을 구현하는데 복잡해진다. 왜냐하면 재귀적인 호출을 통해서 메서드 내에서 여러번의 실행 시간 출력이 실행되기 때문이다. 이러한 문제를 해결하기 위해서는 프록시 객체를 사용해야 한다.

 

재귀적인 팩토리얼 또는 반복적인 팩토리얼의 실행시간을 출력하기 위한 프록시 객체 구현 예시

package chap07;

public class ExeTimeCalculator implements Calculator{
	private Calculator	delegate;

	public ExeTimeCalculator(Calculator delegate) {
		this.delegate = delegate;
	}

	@Override
	public long factorial(long num) {
		long start = System.nanoTime();
		long result = delegate.factorial(num);
		long end = System.nanoTime();
		
		System.out.printf("%s.factorial(%d) 실행 시간 = %d\n",delegate.getClass().getSimpleName(), num, (end-start));
		return result;
	}
}

프록시 객체 실행을 위한 메인

import chap07.ExeTimeCalculator;
import chap07.ImpleCalculator;
import chap07.RecCalculator;

public class MainProxy {
	public static void main(String args[])
	{
		ExeTimeCalculator tlCal1 = new ExeTimeCalculator(new ImpleCalculator());
		System.out.println(tlCal1.factorial(20));
		
		ExeTimeCalculator tlCal2 = new ExeTimeCalculator(new RecCalculator());
		System.out.println(tlCal2.factorial(20));
	}
}
ImpleCalculator.factorial(20) 실행 시간 = 5600
2432902008176640000
RecCalculator.factorial(20) 실행 시간 = 3700
2432902008176640000
  • 위 결과에서 기존 코드를 변경하지 않고 실행 시간을 출력 가능하게 함.
  • 실행 시간을 구하는 코드의 중복을 제거

프록시(Proxy) 객체란 무엇인가?

프록시 객체는 핵심적인 기능의 실행은 다른 객체에게 위임하고 부가적인 기능을 제공하는 객체를 프록시 객체라고 한다.

 

프록시 객체의 특징

  1. 실제 핵심 기능을 실행하는 객체는 대상 객체
    • 위의 예제에서는 ExeTimeCalculator 객체가 프록시이고 ImpeCaculator 객체, RecCalculator 객체가 대상 객체이다.
  2. 특징은 핵심 기능은 구현하지 않는 다는 점이다.
    • ExeTimeCalculator 클래스를 보면 팩토리얼 연산 자체를 구현하지 않고 다른 객체에게 위임하여 실행하는 것을 볼 수 있다.
  3. 프록시는 핵심 기능을 구현하지 않는 대신 여러 객체에 공통으로 적용할 수 있는 기능을 구현한다.
    • 위의 예제에서 팩토리얼 메서드들의 실행 방법은 다르지만 실행 시간을 출력하는 동일한 핵심 기능이 필요하다. 따라서 프록시는 이러한 동일 기능을 구현한다.

 

프록시와 AOP의 관계

이번 절에서 프록시에 대해서 설명한 이유는 위에서 ImpeCaculator, RecCalculator 클래스의 팩토리얼 메소드와 같이 핵심 기능은 집중하고 프록시인 ExeTimeCalculator 클래스는 실행시간 측정이라는 공통 기능 구현에 집중하는 것처럼 공통 기능 구현과 핵심 기능 구현을 분리하는 것이 AOP의 핵심이기 때문이다. 따라서 프록시와 AOP의 관계는 AOP가 제공하는 핵심적인 기능이 프록시라는 것이다.

 

 

References

초보 웹 개발자를 위한 스프링5 프로그래밍 입문, 최범균 저