Web

Ch07. AOP 프로그래밍이란

tose33 2022. 6. 25. 21:40

AOP 프로그래밍 

AOP 프로그래밍이란 Aspect Oriented Programming (관점 혹은 기능 지향 프로그래밍) 이다. 

AOP 프로그래밍은 여러 객체에 공통으로 적용할 수 있는 기능을 분리해서 재사용성을 높여주는 프로그래밍 기법이다.

공통으로 적용할 수 있는 기능을 실행하는 객체를 프록시 (proxy), 실제 핵심 기능을 실행하는 객체를 대상 객체 라고 한다.

 

다음과 같은 Calculator 인터페이스가 있고 

public interface Calculator
{
    public long factorial(long num);
}

 

Calculator 인터페이스를 구현하는 두 개의 클래스 ImpeCalculator 클래스, RecCalculator 클래스가 있다.

 

public class ImpeCalculator implements Calculator
{
    @Override
    public long factorial(long num)
    {
        long result = 1;
        for(long i = 1; i <= num; i++) result *= i;
        return result;
    }
}
public class RecCalculator implements Calculator
{
    @Override
    public long factorial(long num)
    {
        if(num == 0) return 1;
        else return num * factorial(num-1);
    }
}

 

두 클래스 모두 팩토리얼 연산을 수행하는데, ImpeCalculator는 for문으로 계산하고 RecCalculator 클래스는 재귀를 이용해 계산한다.

 

이 두 함수의 실행시간을 측정하고 싶다면 두 가지 방법이 있다.

 

1. 두 클래스의 함수에 각각 시간 측정하는 코드를 작성한다.

2. 두 함수를 실행하는 메인 함수에서 시간 측정하는 코드를 작성한다.

 

하지만 두 방법 모두, 시간 측정하는 기능의 변경이 필요할때 (예를들어 밀리초로 구했었던 값을 나노초로 구하고 싶을때) 코드의 많은 부분을 변경해야 한다.

1번은 두 클래스의 함수 모두 코드를 변경해야하고, 2번은 메인 함수의 ImpeCalculator.factorial()을 실행하는 부분과 RecCalculator.factorial() 을 실행하는 부분을 변경해야 한다. 

 

 

프록시와 대상 객체

이럴때는 핵심 기능인 팩토리얼 연산과 공통 기능인 실행 시간 구하는 부분을 각각 다른 객체가 하도록 하면 된다.

다음 Calculator 인터페이스를 구현하는 ExeTimeCalculator 클래스를 보자.

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();
        // 전달 받은 Calculator 객체로 펙토리얼 계산 시작
        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;
    }
}

이 클래스도 마찬가지로 팩토리얼 연산을 수행한다. 

하지만 이 클래스는 생성자에서 Calculator 객체를 받아서 실제 팩토리얼 연산은 전달받은 객체가 하도록 한다. ExeTimeCalculator 클래스의 factorial 함수 내부에서 자기가 직접 하는 일은 시간을 계산하는 부분 뿐이다. 

 

이제 메인 함수를 보자.

public static void main(String[] args)
{
    ExeTimeCalculator ttCal1 = new ExeTimeCalculator(new ImpeCalculator());
    // ImpeCalculator.factorial 실행
    System.out.println(ttCal1.factorial(20));

    ExeTimeCalculator ttCal2 = new ExeTimeCalculator(new RecCalculator());
    // RecCalculator.factorial 실행
    System.out.println(ttCal2.factorial(20));
}

ExeTimeCalculator를 생성할때, 생성자에 ImpeCalculator 객체를 주느냐, RecCalculator 객체를 주느냐에 따라 실제 실행되는 factorial 함수가 달라진다. 

 

현재 ExeTimeCalculator은 나노초로 함수의 실행 시간을 구하고 있는데, 밀리초로 바꾸고 싶다면 ExeTimeCalculator 클래스의 factorial 함수의 해당 부분만 바꿔주면 된다. 

 

이렇게 핵심 기능인 팩토리얼 연산을 하는 ImpeCalculator, RecCalculator 클래스를 프록시 (proxy) 라고 한다.

공통 기능인 시간 측정을 하는 ExeTimeCalculator 클래스를 대상 객체 라고 한다.

 

 

 

 

 

출처 : 스프링5 프로그래밍 입문 (최범균 저)