AOP는 관점(Aspect)지향 프로그래밍으로, 관점을 기준으로 다양한 기능을 분리하여 보는 프로그래밍이다. 관점(Aspect)이란, 부가 기능과 그 적용처를 정의하고 합쳐서 모듈로 만든 것이다.
OOP와 이름이 비슷하여 상반된 개념 같지만, 관점지향 프로그래밍은 객체지향 프로그래밍을 보완하기 위해 쓰인다. 기존 객체(Object) 지향은 목적에 따라 클래스를 만들고 객체를 만들었다. 따라서 핵심 비즈니스 로직이든, 부가 기능의 로직이든 하나의 객체로 분리하는데 그치고, 그래서 이 기능들을 어떻게 바라보고 나눠쓸지에 대한 정의가 부족하다는 단점이 있다.
보통 비즈니스 웹 애플리케이션이라면 사업에 핵심적인 핵심 비즈니스 로직이 있고, 애플리케이션 전체를 관통하는 부가 기능 로직이 있다. 이를 횡단 관심사(cross-cutting concerns)라고 한다. (종류는 로깅, 보안, 트랜젝션이 있다.)
횡단 관심사의 코드를 핵심 비즈니스 로직의 코드와 분리하여, 코드의 간결성을 높이고 변경에 유연함과 무한한 확장이 가능하도록 하는 것이 AOP의 목적이다.
AOP를 적용하는 방식은 여러 가지가 있다.
컴파일 시점 적용 방식은 AspectJ 컴파일러가 일반 .java
파일을 컴파일할 때 부가기능을 넣어서 .class
파일로 컴파일해주는 것을 의미한다. 이 동작을 에스팩트와 실제 코드를 연결하는 위빙(weaving)이라고 부른다.
JVM내 클래스로더에 .class
파일을 올리는 시점에 바이트 코드를 조작해 부가기능 로직을 추가하는 방식이다.
컴파일, 클래스 로딩, main() 메서드의 실행 이후에 자바가 제공하는 범위내에 부가 기능을 적용하는 방식이다. 이미 런타임 중이라 코드를 조작하기 어려워 스프링, 컨테이너, DI, 빈 등 여러 개념과 기능을 총동원하여 프록시를 통해 부가 기능을 적용하는 방식이다.
프록시는 메서드 실행 시점에서만 다음 타겟을 호출할 수 있기 때문에, 런타임 시점에 부가기능을 적용하는 방식은 메서드의 실행 지점으로 제한된다.
Spring AOP는 런타임 시점에 적용하는 방식을 사용한다. 이유는 컴파일 시점과 클래스 로딩 시점에 적용하려면 별도의 컴파일러와 클래스로더 조작기를 써야 하는데, 이것을 정하고 사용 및 유지하는 과정이 매우 어렵고 복잡하기 때문이다.
Type | 설명 |
---|---|
Before | 조인포인트 실행 이전에 실행, 일반적으로 리턴타입 void |
After returning | 조인포인트 완료후 실행 (ex. 메서드가 예외없이 실행될 때) |
After Throwing | 메서드가 예외를 던지는 경우 실행 |
After (finally) | 조인포인트의 동작과 관계없이 실행 |
Around | 메서드 호출 전후에 수행(조인포인트 실행 여부 선택, 반환 값 변환, 예외 변환, try~catch~finally 구문 처리 가능 등), 가장 강력한 어드바이스이다. |