AOP (관점 지향 프로그래밍)
AOP는 흔히 '관점지향프로그래밍'이라고 해석이 되어진다. 하지만 관점이라는 용어로 접근을 하게 되면 이해하기가 어려운 점이 많아, 많은 개발자들이 관점(aspect) 보다는 관심사(concern)이라는 말로 사용한다. 여기서 말하는 관심사는 개발 시에 필요한 고민이나 염두에 두어야 하는 일이라고 생각할 수 있다.
관심사 종류
1. 파라미터가 올바르게 들어왔는가?
2. 이 작업을 하는 사용자가 적절한 권한을 가진 사용자인가?
3. 이 작업에서 발생할 수 있는 모든 예외는 어떻게 처리해야 하는가?
위와 같은 고민들은 핵심적인 내용들은 아니지만, 코드를 온전하게 만들기 위해서 필요한 고민들이다. 개발자들은 이러한 공통적인 관심을 고민하고 코드에 반복적으로 사용하게 된다. AOP는 이러한 고민에 대하여 추구하는 것은 '관심사의 분리(separate concerns)'라는 것이다. 그리기에 AOP는 개발자가 염두에 두어야 하는 일들을 별도의 관심사로 분리하고, 핵심 비즈니스 로직만 작성할 것을 권장한다.
관심사 == 주변로직?
주변로직을 설명하기 위해 예를 하나 들어보자면, 두 수를 가지고 나눗셈을 하려고 한다면 비즈니스 로직에서는 두 수를 나누기만 하면 된다는 것이다. 그렇다면 여기서 주변로직은 0이라는 값만 비즈니스 로직에 입력이 되었는가만 확인을 하면 되는 것이다. 관심사는 바로 이런 가장 중요한 로직은 아니지만, 사전 조건이나 사후 조건등이라고 간주할 수 있다.
AOP는 과거에 개발자가 작성했던 '관심사 + 비즈니스 로직'을 분리해서 별도의 코드로 작성하도록 하고, 실행할 때 이를 결합하는 방식으로 접근한다. 과거에 비즈니스 로직을 작성하면서 그 내부에 필요한 관심사를 처리하던 방식과 정반대의 접근 방식이라고 볼 수 있다. 실제 실행은 결합된 상태의 코드가 실행되기 때문에 개발자들은 핵심 비즈니스 로직에만 근거해서 코드를 작성하고, 나머지는 어떤 관심사들과 결합할 것인지를 설정하는 것만으로 모든 개발을 마칠 수 있다.
예를 들어, AOP를 이용하면 작성된 모든 메서드의 실행 시간이 얼마인지를 기록하는 기능을 기존 코드의 수정 없이도 작성할 수 있고, 잘못된 파라미터가 들어와서 예외가 발생하는 상황을 기존 코드의 수정 없이 제어가 가능하다. 스프링이 AOP를 지원한다는 것이 스프링의 가장 중요한 특징 중에 하나로 말하게 된 이유 역시 별도의 복작한 설정이나 제약 없이 스프링 내에서 간편하게 AOP 기능을 구형할 수 있기 때문이다.
AOP 용어
개발자의 입장에서 AOP를 적용한다는 것은 기존의 코드를 수정하지 않고도 원하는 관심사(cross-concern)들을 엮을 수 있기 때문이다. 위 그림에서 Target에 해당하는 것은 바로 개발자가 작성한 핵심 비즈니스 로직을 가지는 객체이다.
Target은 순수한 비즈니스 로직을 의미하고, 어떠한 관심사들과 관계를 맺지 않는다. 그러기에 이것을 순수한 코어(core) 라고 볼 수 있다. Target을 전체적으로 감싸고 있는 존재를 Proxy하고 하며, Proxy는 내부적으로 Target을 호출하지만, 중간에 필요한 관심사들을 거쳐서 Target을 호출하도록 자동 혹은 수동으로 작성이된다. Proxy의 존재는 직접 코드를 통해서 구현하는 경우도 있지만, 대부분의 경우 스프링 AOP 기능을 이용해서 자동으로 생성되는 (auto-proxy) 방식을 이용한다. JoinPoint는 Target 객체가 가진 메서드를 말하며, 외부에서의 호출은 Proxy 객체를 통해서 Target 객체의 JoinPoint를 호출하는 방식이라고 생각하면 된다.
JointPoint는 Target이 가진 여러 메소드라고 보면 된다.(스프링 AOP에서는 메서드만이 JoinPoint가 된다) Target에는 여러 메서드가 존재하기 때문에 어떤 메서드에 관심사를 결합할 것인지 결정해야 한다. 이러한 결정을 'PointCut' 이라고 한다.
Poincut은 관심사와 비즈니스 로직이 결합되는 지점을 결정하는 것이다. 선택된 JointPoint는 결합이 완성된 상태이므로 메서드를 호출하게 되면 자동으로 관심사가 결합된 상태로 동작하게 된다.
AOP에 사용되는 어노테이션
아래 테이블에 있는 어노테이션들은 실제 AOP 메소드를 작성 되면서 실행되는 순서를 정할 때 사용이 된다.
구분 | 설명 |
@Before | Target의 JoinPoint를 호출하기 전에 실행되는 코드. 코드의 실행 자체에는 관여 할 수 없음. |
@AfterReturning | 모든 실행이 정상적으로 이루어진 후에 동작하는 코드. |
@AfterThrowing | 예외가 발생한 뒤에 동작하는 코드. |
@After | 정상적으로 실행되거나 예외가 발생했을 때 구분 없이 실행되는 코드. |
@Around | 메서드의 실행 자체를 제어 할 수 있는 가장 강력한 코드. 직접 대상 메서드를 호출하고 결과나 예외를 처리할 수 있음. |
AOP에서 Target은 결과적으로 Pointcut에 의해서 자신에게는 없는 기능들을 가지게 된다. 또한, Pointcut은 다양한 형태로 선언해서 사용할 수 있는데 사용되는 설정은 다음과 같다.
구분 | 설명 |
excution(@excution) | 메서드를 기준으로 Pointcut을 설정함. |
within(@within) | 특정한 타입(클래스)을 기준으로 Pointcut을 설정함. |
this | 주어진 인터페이스를 구현한 객체를 대상으로 Pointcut을 설정함. |
args(@args) | 특정한 파라미터를 가지는 대상들만을 Pointcut을 설정함. |
@annotation | 특정한 어노테이션이 적용된 대상들만 Pointcut으로 설정함. |
'Backend > Spring' 카테고리의 다른 글
스프링 핵심 원리 - 기본편(정리) 1편 (0) | 2023.05.01 |
---|---|
스프링 핵심 원리 - 입문편(정리) (0) | 2023.05.01 |
MVC 모델과 DispatcherServlet (0) | 2023.01.25 |
@Autowired @Quelifier @Component @Value (0) | 2023.01.07 |
Bean을 .xml 통해 만들어 보기 (0) | 2023.01.07 |