본문 바로가기

Java/Spring

[Spring] AOP 정리

AOP(Asepect-Oriented Programming)

 - '관점 지향 프로그래밍' 이라는 의미로 번역되는데, 객체지향에서 특정 비즈니스 로직에 걸림돌이 되는 공통 로직을 제거할 수 있는 방법을 제공한다.

- AOP를 적용하면 기존의 코드에 첨삭없이, 메서드의 호출 이전 혹은 이후에 필요한 로직을 수행하는 방법을 제공한다.

 

- AOP는 흔히 '관점 지향 프로그래밍'이라는 용어로 번역되는데, 이때 '관점(Aspect)'이라는 용어는 개발자들에게 '관심사(concern)'이라는 말로 통용된다. '관심사'는 개발 시 필요한 고민이나 염두에 두어야 하는 일이라고 생각할 수 있는데, 코드를 작성하면서 염두에 두는 일들을 주로 다음과 같다.

   

     ∙ 파라미터가 올바르게 들어왔을까?

     ∙ 이 작업을 하는 사용자가 적절한 권한을 가진 사용자인가?

     ∙ 이 작업에서 발생할 수 있는 모든 예외는 어떻게 처리해야하는가?

 

- 위와 같은 고민들은 '핵심 로직'은 아니지만, 코드를 온전하게 만들기 위해서 필요한 고민들인데 전통적인 방식에서는 개발자가 반복적으로 이러한 고민을 코드에 반영하게 된다. AOP는 이러한 고민에 대한 문제를 조금 다른 방식으로 접근한다.

- AOP가 추구하는 것은 '관심사의 분리(seperate concerns)"이다.  즉, AOP는 개발자가 염두에 두어야 하는 일들은 별도의 '관심사'로 분리하고, 핵심 비즈니스 로직만을 작성할 것을 권장한다.

 

- '관심사'를 쉽게 생각해보면 '주변 로직'으로 표현이 가능하다. 예를 들어 나눗셈을 구현한다고 치면 '핵심 로직'은 두 개의 숫자를 나누는 것이지만, '주변 로직'은 0을 나누는 것이 아닌지 등을 체크하는 것이다. '관심사'는 바로 이런 가장 중요한 로직은 아니지만, 사전 조건이나 사후 조건 등이라고 간주할 수 있다.

 

관심사 + 비즈니스 로직

- AOP는 과거에 개발자가 작성했던 '관심사 + 비즈니스 로직'을 분리해서 별도의 코드로 작성하도록 하고, 실행할 때 이를 결합하는 방식으로 접근한다.

- 과거에 비즈니스 로직을 작성하면서 그 내부에 필요한 '관심사'를 처리하던 방식과 정반대의 접근 방식이라고 볼 수 있는데, 개발자가 작성한 코드와 분리된 관심사를 구현한 코드를 컴파일 혹은 실행시점에 결합시킨다.

- 실제 실행은 결한됩 상태의 코드가 실행되기 때문에 개발자들은 핵심 비즈니스 로직에만 근거해서 코드를 작성하고, 나머지는 어떤 관심사들과 결합할 것 인지를 설정하는 것 만으로 모든 개발을 마칠 수 있게 된다.

 

✓ AOP 용어들

- AOP는 기존의 코드를 수정하지 않고, 원하는 기능들과 결합할 수 있는 패러다임이다.

 

 

- 개발자의 입장에서 AOP를 적용한다는 것은 기존의 코드를 수정하지 않고도 원하는 관심사(cross-concern)들을 엮을 수 있다는 점이다.

- 위의 그림에서 Target에 해당하는 것이 바로 개발자가 작성한 핵심 비즈니스 로직을 가지는 객체이다.

- Target은 순수한 비즈니스 로직을 의미하고, 어떠한 관심사들과도 관계를 맺지 않는다. (순수한 Core)

 

- Target을 전체적으로 감싸고 있는 존재를 Proxy라고 한다. Proxy는 내부적으로 Target을 호출하지만, 중간에 필요한 관심사들을 거쳐서 Target을 호출하도록 자동 혹은 수동으로 작성된다.

- Proxy의 존재는 직접 코드를 통해서 구현하는 경우도 있지만, 대부분의 경우 스프링 AOP기능을 이용해서 자동으로 생성되는(auto-proxy) 방식을 이용한다.

- JoinPoint는 Target 객체가 가진 메서드이다.

- 외부에서는 호출은 Proxy 객체를 통해서 Target의 객체의 JoinPoint 를 호출하는 방식으로 이해할 수 있다.

 

- JonPoint는 Target이 가진 여러 메서드라고 보면 된다.(엄밀하게 스프링 AOP에서는 메서드만이 JoinPoint가 된다.)

- Target에는 여러 메서드가 존재하기 때문에 어떤 메서드에 관심사를 결합할 것인지를 결정해야 하는데 이 결정을 'PointCut'이라고 한다.

 

- PointCut은 관심사와 비즈니스 로직이 결합되는 지점을 결정하는 것이다.

- 앞의 Proxy는 이 결합이 완성된 상태이므로 메서드를 호출하게 되면 자동을 관심사가 결합된 상태로 동작하게 된다.
- 관심사(concern)는 위의 그림에서 AspectAdive라는 용어로 표현되어 있다.

- Aspect는 조금 추상적인 개념을 의미하는데, Aspect는 관심사 자체를 의미하는 추상명사라고 볼 수 있고, Adivce는 Aspect를 구현한 코드이다. 

 

- Adivce는 실제 걱정거리를 분리해 놓은 코드를 의미한다. Advice는 동작 위치에 따라 구분된다.

구분 설명
Before Advice Target의 Joinpoint 를 호출하기 전에 실행되는 코드이다. 코드의 실행 자체에는 관여할 수 없다.
After Returning Advice 모든 실행이 정상적으로 이루어진 후에 동작하는 코드이다.
AfterThrowing Advice 예외가 발생한 뒤에 동작하는 코드이다.
After Advice 정상적으로 실행되거나 예외가 발생했을 때 구분없이 실행되는 코드이다.
Around Advice 메서드의 실행 자체를 제어할 수 있는 가장 강력한 코드이다. 직접 대상 메서드를 호출하고 결과나 예외를 처리할 수 있다.

 

 

- Advice는 과거의 스프링에서는 별도의 인터페이스로 구현되고, 이를 클래스로 구현하는 방식으로 제작했으나 스프링 3버전 이후에는 어노테이션만으로도 모든 설정이 가능하다.

- Target에 어떤 Advice를 적용할 것인지는 XML을 이용한 설정을 이용할 수 있고, 어노테이션을 이용하는 방식을 이용할 수 있다.

 

- Poincut은 Advice를 어떤 JonPoint에 결합할 것인지를 결정하는 설정이다.

- AOP에서 Target은 결과적으로 Pointcut에 의해서 자신에게는 없는 기능들을 가지게 된다.

- Pointcut은 다양한 형태로 선언해서 사용할 수 있다.

구분 설명
execution(@execution) 메서드를 기준으로 Pointcut을 설정한다.
within(@within) 특정한 타입(클래스)을 기준으로 Pointcut을 설정한다.
this 주어진 인터페이스를 구현한 객체를 대상으로 Pointcut을 설정한다.
args(@args) 특정한 파라미터를 가지는 대상들만을 Pointcut으로 설정한다.
@annotation 특정한 어노테이션이 적용된 대상들만을 Pointcut으로 설정한다.