
AOP란 핵심 관심 사항과 공통 관심 사항을 기준으로 모듈화하는 프로그래밍 방식을 말합니다. 이러한 방식은 OOP의 한계를 보완하기 위해 사용하는데, 핵심 관심 사항에 집중되어 있는 여러 클래스에서 발생한 동일한 작업을 수행하는 중복된 코드들을 모듈화하여 코드의 가독성과 재사용성 향상을 달성할 수 있습니다.
공통 관심 사항이란?
공통 관심 사항이란 애플리케이션 전반에 걸쳐 반복적으로 적용되는 기능을 의미하며, 특정 클래스나 모듈에 국한되는 것이 아닌 여러 클래스에서 동일한 로직이 반복되는 특징을 가지고 있습니다. 이로 인해, 유지보수성과 확장성 저하의 주요 원인이 됩니다.
Spring AOP는 Spring 프레임워크에서 AOP를 적용하기 위해 기본적으로 제공하는 라이브러리입니다.
Spring AOP는 다음과 같은 특징을 가지고 있습니다.
왜, AspectJ만 다양한 옵션을 제공하나요?
프록시 방식을 사용하여 런타임 시점에 Aspect를 적용하는 Spring AOP와 달리 AspectJ는 바이트코드 변환 방식 사용하여 컴파일과 클래스 로딩 시점에 Aspect를 결합(Weaving)하기 때문입니다. 하지만, Spring AOP도 AspectJ의 바이트코드 변환 기능을 활성화하면 적용할 수 있습니다.
Spring AOP는 프록시 디자인 패턴을 기반으로 동작하며 실제 객체 대신 프록시 객체를 통해 Advice를 실행합니다. 이때, 프록시 객체는 실제 객체의 역할을 대신 수행하는 객체를 말합니다.
프록시 디자인 패턴이란?
프록시 디자인 패턴이란 특정 대상 객체에 접근하기 전 접근에 대한 흐름을 가로채 접근을 필터링하거나 수정하는 등의 역할을 하는 계층이 있는 디자인 패턴입니다.
이에 대한 실행 과정은 다음과 같습니다.
@Before, @Around@AfterThrowing@After, @Around@AfterReturingAOP를 사용하기에 앞서 Target, JoinPoint, PointCut, Advice, Weaving 등의 개념을 이해하는 것이 중요합니다.
Target, Join Point, PointCut의 개념은 다음과 같습니다.
코드를 예시로 3가지 개념의 상관관계를 표현하면 다음과 같습니다.
Advice는 특정 시점에 실제로 실행할 로직을 정의한 것을 말하며, 일반적으로 PointCut과 함께 사용하여 특정 대상에 대해 실행합니다. 다음 코드 예시와 같이 실행 시점에 따라 @Before, @After, @AfterReturning, @AfterThrowing, @Around 등의 어노테이션을 제공합니다.

Weaving은 Aspect가 Target에 결합되는 과정입니다. 이때, 결합 시점에 따라 Compile-time(컴파일 시점), Load-time(클래스 로딩 시점), Run-time(실행 시점)으로 구분할 수 있습니다.
앞에서 배운 AOP 개념들을 적용하여 Aspect를 정의할 수 있습니다. 이를 활용하여 객체 지향 프로그래밍에 AOP를 적용하여 공통 관심사를 분리한 결과는 다음과 같습니다.

AOP는 핵심 관심사와 공통 관심사를 구분하는 프로그래밍 방식으로, 객체 지향 프로그래밍의 한계를 보완할 수 있습니다.
객체 지향 프로그래밍의 경우 핵심 관심사에 대한 로직에 집중되어 있어 부가적인 기능들의 코드 중복이 발생할 수 있습니다. 이러한, 공통 관심사들을 모듈화함으로써 재사용성과 가독성을 개선할 수 있는 벙빕이 AOP 입니다.
Spirng AOP는 Spring 프레임워크에서 AOP를 사용하기 위헤 제공하는 기본 라이브러리로 프록시 디자인 패턴을 기반으로 동작합니다.
Spring AOP의 경우 프록시 디자인 패턴을 기반으로 작동하며, Spring Bean만 AOP 적용이 가능합니다. 또한, AOP 적용 대상의 메서드들만 Join Point의 대상이 됩니다. 반면에, AspectJ은 바이트코드 변환 방식을 기반으로 작동하기 때문에, 모든 클래스를 대상으로 AOP 적용이 가능하며 생성자, 필드, Static 메서드 또한 Join Point 대상으로 사용할 수 있습니다.
프록시 객체는 Spring AOP를 적용하기 위해 사용하는 객체입니다. AOP 대상인 Bean을 호출 했을 때 프록시 객체가 이를 인터셉트하여 실제 객체가 아닌 프록시 객체를 활용해 수행합니다.
프록시 객체는 IoC 컨테이너가 Bean 생성한 후 이를 감싸는 프록시 객체를 생성하여 관리합니다. 이때, 인터페이스 구현 여부에 따라 JDK 동적 방식과 CGLIB 방식중 하나를 선택하여 생성을 수행합니다. Spring Boot의 경우 CGLIB이 기본 생성 방식인 것으로 알고 있습니다.
Target, Join Point, PointCut, Advice, Weaving 등이 있습니다.
Target의 경우 AOP 적용 대상인 객체를 말하며, Join Point는 해당 객체에 포함된 메서드를 말합니다. Join Point 중 필터링을 통해 실제 AOP 적용 대상으로 사용하는 메서드를 PointCut, 이를 통해 실제로 실행하고자 하는 로직을 정의한 것을 Advice라 합니다. 이를 통틀어 Aspect라 하며, 이를 Target과 결합하는 것이 Weaving입니다.