AOP 가 등장한 배경
AOP 란 (Aspect-Oriented Programing) OOP 의 한계를 극복하기 위해 등장한 패러다임입니다.
OOP는 대부분의 기능을 캡슐화 할 수 있지만, 중복되는 로직이나 횡단관심사의 경우에는 분리하기 어려운 경우가 많습니다.
횡단관심사
횡단 관심사란 소프트웨어 개발에서 여러 계층이나 묘둘에 걸쳐 공통적으로 영향을 미치는 관심사입니다.
예로는 로깅, 트랜잭션 관리, 성능 모니터링이 있습니다.

이를 해결하기 위해 AOP 패러다임을 이용해 횡단 관심사를 분리해 OOP 의 장점을 살리고 중복되는 로직을 줄일 수 있게 된 것입니다.
조금 더, 깊게 생각해보면 OOP 의 5대 원칙 중 하나인 SRP 를 위배 한다는 것을 알 수 있습니다. AOP 패러다임을 사용하지 않는다면 비즈니스 로직을 구현한 메서드에 공통 관심사가 뒤엉켜 하나의 책임이 아닌 다중 책임을 가지게 됩니다. 또한 AOP 를 통해 확장에는 열려있어야 하는 OCP 의 원칙도 지킬 수 있게 됩니다.
위에서 언급한 중복, 로직의 뒤엉킴 등의 문제를 해결, 횡단 관심사를 분리해 중앙화하고 재사용할 수 있도록 한 것이 관점의 개념입니다.
결론적으로 AOP 는 횡단 관심사를 별도의 모듈로 분리하여 코드의 중복, 유지보수가 편리하게 만들어주는 프로그래밍의 패러다임이라고 할 수 있습니다.
“큰 힘에는 큰 책임이 따른다!”라는 말처럼, 애스펙트는 강력한 도구이므로 신중하게 사용하지 않으면 원하는 목적과는 정반대로 유지 관리하기 어려운 앱이 될 수 있다. (피터 파커)
관점이라는 도구는 강력한 도구이기 때문에 신중하게 사용해야 합니다.
AOP 실행 과정
위에서 우리는 AOP 의 등장 배경에 대해 함께 생각해보는 시간을 가졌습니다. 그렇다면 AOP 는 어떻게 사용, 실행 되는지 알아보는 시간을 가지면 좋겠습니다.
AOP의 실행과정을 이해하기 위해서는 몇가지의 개념이 필요합니다. 개념에 대해서는 간단하게 언급하고 궁금하다면 더 찾아보는 것을 추천드립니다.
- 프록시
프록시란 객체와 객체 간의 연결을 직접연결이 아닌 프록시라는 대리자를 통해 간접적으로 연결하는 것을 말합니다.
이 과정에서 추가적인 로직이나 필요작업을 추가해줄 수 있습니다.
- 팩토리 패턴
팩토리 패턴이란 객체 생성을 담당하는 공장을 만들어 필요 시 객체를 생성하는 역할을 분리 하는 것입니다.
이렇게 될 경우 클래스에 직접적인 객체 생성을 하지 않고 참조를 통해 객체를 얻어올 수 있습니다. 유지보수와 객체 생성의 로직을 캡슐화 할 수 있는 장점이 생깁니다.
- AOP 의 핵심 용어들
Aspect : 횡단관심사를 분리해 모듈화 한 것
JoinPoint : 프로그램 실행 중 횡단 관심사를 적용할 수 있는 지점
PointCut : JoinPoint 를 필터링 할 수 있는 규칙
Advice : JoinPoint 에서 실행되는 실제 동작
Target : AOP 가 적용되는 객체
접은 글의 개념을 어느 정도 숙지한 상태에서 AOP 의 실행과정을 살펴보도록 하겠습니다.
- 개발자의 AOP 설정 (@Aspect , XML, Java Config)
- 스프링 컨테이너 초기화 (BeanPostProcessor 등록 (AnnotationAwareAspectJAutoProxyCreator 나 AutoProxyCreator 중 하나가 등록 됨.))
- 컨테이너가 모든 빈을 생성하고 초기화 합니다. 등록 된 AutoProxyCreator 가 빈 생성 과정에서 AOP 적용 대상을 식별합니다(@Aspect , PointCut 매칭 클래스)
- 프록시( JDK 동적 프록시(인터페이스가 있는 경우 사용) , CGLIB 프록시(클래스 기반 프록시 생성) )를 생성합니다(빈 후처리기의 개념이 필요 함). 프록시 객체 내부에 AdvisedSupport 객체가 생성되며, 다음정보를 가집니다. Target 객체, Advisor 목록(Advice, PointCut), 프록시 설정 정보
- 빈 팩토리는 원본 빈 대신 생성된 프록시 객체를 컨테이너에 등록하게 됩니다.
- 클라이언트가 빈의 메서드를 호출
- 프록시가 호출을 가로채고 Advisor 를 확인 Advice 실행 후 Target 객체의 메서드를 호출
- 결과 반환 하거나 추가 처리를 수행
예시 코드
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("Before method: " + joinPoint.getSignature().getName());
}
}
@Service
public class MyService {
public void doSomething() {
System.out.println("Doing something...");
}
}
// Main Application
MyService service = context.getBean(MyService.class);
service.doSomething();
PointCut에 해당되는 MyService 를 AOP 대상으로 식별하고, 프록시 객체를 생성합니다. 클라이언트가 doSomething() 메서드를 호출했을 때, 프록시 객체가 호출 되고 log 를 찍고 service 의 메서드가 실행되는 것을 알 수 있습니다.
스프링 공식문서 내용 정리
Spring AOP 는 순수 자바로 구현되었기 때문에 특별한 컴파일 과정이 필요하지 않습니다.
궁극적인 목표는 가장 완벽한 AOP 구현을 제공하는 것이 아니고 AOP 구현과 Spring IoC 간의 긴밀한 통합을 제공해 엔터프라이즈 애플리케이션의 일반적인 문제를 해결하는 데 도움이 되는 것입니다.
AspectJ Support 는 어노테이션이 있는 일반 Java 클래스로 관점을 선언하는 스타일입니다.
Declaring Advice 를 통해 메서드의 실행 시점을 지정해 사용이 가능합니다.
TMI
위빙(weaving) 이란?
DI를 사용하든 컨텍스트에서 빈을 얻을 때는 언제나 빈 대신 프록시 객체를 받게 된다. 이렇게 래핑 하는 것을 위빙이라고 한다.
오늘은 AOP 에 대해 알아보았습니다. 아직은 부족함이 많지만 끊임없이 성장해보도록 하겠습니다. 감사합니다.