관점 지향 프로그래밍(AOP)
AOP(Aspect-Oriented Programming)는 횡단 관심사(cross-cutting concerns)를 핵심 비즈니스 로직에서 분리해 모듈성을 높이는 프로그래밍 방식이다. OOP(객체 지향 프로그래밍)를 보완하는 개념으로, OOP가 클래스를 중심으로 동작한다면, AOP는 횡단 관심사를 Aspect라는 객체로 처리한다. Aspect는 언제, 어디서, 무엇을 할지에 대한 정보를 담아 핵심 로직에 영향을 주지 않고 부가 기능을 분리할 수 있게 해준다.
AOP 용어
- Aspect
부가기능을 모듈화한 것
Advice(What & When) + Pointcut(Where)
- Target
Aspect가 적용될 객체
(e.g., 클래스, 메소드)
- Advice
Aspect가 특정 JoinPoint에서 해야 하는 부가 기능(What & When)
types: before, after, after-returning, after-throwing, around
- JoinPoint
Advice가 적용될 수 있는 지점
Spring AOP에서는 항상 메서드 진입 시점
- Pointcut
어떤 JoinPoint에 Advice를 적용할 지 결정하는 기준
Advice가 적용되지 않는 JoinPoint도 있다.
- Weaving
Pointcut에 의해 결정된 Target의 JoinPoint에 Advice(부가 기능)를 삽입하는 과정
types: 컴파일 타임, 클래스 로드 타임, 런타임 위빙
Spring AOP에서는 런타임 위빙만 사용한다.

AOP 구현 방식
스프링 AOP는 @AspectJ
애노테이션 방식과 XML 방식 두 가지로 구현 가능하다. 이 중 @AspectJ
방식이 많이 사용된다.
@AspectJ
- 설정 클래스에
@EnableAspectJAutoProxy
- Aspect 선언
- Pointcut 선언
- Advice 선언
Proxy
스프링 AOP는 프록시(Proxy)를 기반으로 동작한다. 프록시는 원래 객체(Target)를 감싸는 대리 객체로, 기존 객체의 인터페이스는 유지하면서 추가적인 동작을 수행한다. 이를 통해 핵심 비즈니스 로직을 건드리지 않고 부가 기능을 더할 수 있다.
프록시의 역할
- Intercept(가로채기): 프록시는 클라이언트가 Target 객체를 호출할 때 그 호출을 가로채고, Advice에 정의된 부가 기능을 먼저 수행한 뒤 Target의 핵심 기능을 실행함.
- 비즈니스 로직과 부가 기능 분리: 프록시는 핵심 비즈니스 로직과 부가 기능을 분리해 코드 중복을 줄이고, 유지 보수성을 높임.
Aspect 우선순위
하나의 JoinPoint에 여러 Advice가 적용될 경우, 실행 순서가 중요해진다. 예를 들어 로깅과 보안 기능이 함께 적용될 때, 순서를 지정하지 않으면 예상치 못한 결과가 나올 수 있다. 이를 해결하기 위해 스프링에서는 @Order 어노테이션이나 Ordered 인터페이스를 사용해 우선순위를 지정할 수 있다. 숫자가 작을수록 우선순위가 높으며, 우선순위가 높은 Aspect가 가장 바깥에서 실행된다.
어노테이션
어노테이션은 코드 사이에 주석처럼 사용되어 프로그램에 추가 정보를 제공하고, 특정 기능을 수행하도록 만드는 기술이다. 메타데이터의 일종으로, 여러 용도로 사용될 수 있다.
어노테이션의 용도
- 컴파일러에 문법 체크 정보 제공: 코드 작성 시 문법 오류를 컴파일러가 검증할 수 있도록 정보를 제공
- 소프트웨어 개발 도구에서 코드 자동 생성 지원: 빌드나 배포 과정에서 자동으로 코드를 생성하도록 정보를 제공
- 런타임 시 특정 기능 실행: 런타임 시 동작할 기능에 대한 정보를 제공
Spring에서 제공되는 대부분의 어노테이션은 3번 용도로 사용되며, 런타임 시 특정 기능을 수행하는 데 필요한 정보를 제공한다.
커스텀 어노테이션
커스텀 어노테이션은 사용자가 직접 정의한 어노테이션을 의미한다. 이를 통해 개발자는 특정 목적에 맞는 어노테이션을 만들 수 있다.
커스텀 어노테이션 정의 방법
- @interface 타입으로 정의: 커스텀 어노테이션은 @interface로 선언됨
- 메타 어노테이션 추가: 다른 어노테이션에 적용되는 어노테이션을 메타 어노테이션이라고 부름
주요 메타 어노테이션
@Target
어노테이션 적용 대상
ElementType.PACKAGE : 패키지 선언
ElementType.TYPE : 타입 선언
ElementType.ANNOTATION_TYPE : 어노테이션 타입 선언
ElementType.CONSTRUCTOR : 생성자 선언
ElementType.FIELD : 멤버 변수 선언
ElementType.LOCAL_VARIABLE : 지역 변수 선언
ElementType.METHOD : 메서드 선언
ElementType.PARAMETER : 전달인자 선언
ElementType.TYPE_PARAMETER : 전달인자 타입 선언
ElementType.TYPE_USE : 타입 선언
@Retention
어노테이션 보존 범위
RetentionPolicy.SOURCE : 컴파일 전까지만 유효
RetentionPolicy.CLASS : 컴파일러가 클래스를 참조할 때까지 유효
RetentionPolicy.RUNTIME : 컴파일 이후 런타임 시기에도 JVM에 의해 참조가 가능
@Documented
Javadoc 포함 여부
@Inherited
자식에게 어노테이션 상속 여부
커스텀 어노테이션 기반 AOP
- AOP 의존성 추가: build.gradle이나 pom.xml에 AOP 의존성 추가
- 커스텀 어노테이션 작성: @interface로 어노테이션 정의
- Aspect 생성: @Aspect를 이용
- Pointcut, Advice 작성: Pointcut과 Advice를 정의해 특정 JoinPoint에 부가 기능을 적용
- 실행: 작성한 커스텀 어노테이션과 AOP 설정을 기반으로 애플리케이션에서 동작시킴
