스프링 AOP 개념
- 김영한님의 스프링 원리 - 고급편 강의를 바탕으로 AOP의 등장 배경과 주요 개념, 적용 방식, 용어 정리, 그리고 스프링 AOP와 AspectJ의 차이를 정리함
핵심 기능과 부가 기능
개요
-
애플리케이션 로직은 크게 두 가지로 구분됨
구분 설명 예시 핵심 기능 해당 객체가 제공하는 고유 기능 OrderService의 주문 로직부가 기능 핵심 기능을 보조하기 위한 기능 로그 추적, 트랜잭션 관리 -
부가 기능은 단독으로 사용되지 않고, 핵심 기능과 함께 사용됨

횡단 관심사
개요
- 부가 기능은 보통 여러 클래스에 걸쳐 공통으로 사용됨
-
이처럼 여러 모듈에 공통적으로 적용되는 부가 기능을 횡단 관심사라고 함

부가 기능 적용 시 문제점
- 부가 기능 적용 시 수많은 반복이 발생함
- 여러 곳에 퍼져 중복 코드가 생성됨
- 부가 기능 변경 시 모든 클래스를 수정해야 함
- 적용 대상 변경 시에도 대규모 수정이 필요함
일반적인 OOP 방식으로는 이 문제를 해결하기 어려움
AOP 소개 - 애스펙트 (Aspect)
부가 기능을 분리하고 한 곳에서 관리

- Aspect = 어드바이스(부가 기능) + 포인트컷(어디에 적용할지)
- AOP는 OOP를 대체하는 것이 아니라, OOP의 부족한 부분(횡단 관심사 처리)을 보조하는 목적으로 개발됨
AspectJ 프레임워크
- AOP의 대표적 구현체이며, 스프링 AOP는 AspectJ의 문법을 차용하되 기능의 일부만 제공함
- AspectJ가 지원하는 기능
- 횡단 관심사의 깔끔한 모듈화
- 오류 검사 및 처리
- 동기화
- 성능 최적화 (캐싱)
- 모니터링 및 로깅
AOP 적용 방식
개요

컴파일 시점 (Compile-time Weaving)
1
2
3
OrderService.java
↓ (AspectJ 컴파일러)
orderService.class ← 부가 기능 코드가 실제로 삽입됨
- AspectJ 전용 컴파일러가 필요함
- 컴파일된
.class파일에 부가 기능 코드가 직접 포함됨 - 특별한 컴파일러 설정이 필요하여 복잡함
클래스 로딩 시점 (Load-time Weaving)
1
2
3
orderService.class
↓ (AspectJ 클래스 로더 조작기)
JVM 내부 → 부가 기능이 추가된 클래스로 로드됨
java -javaagent옵션으로 클래스 로더 조작기를 지정함.class→ JVM 적재 직전에 바이트코드를 조작함- 수많은 모니터링 툴이 이 방식을 사용함
- 운영 설정이 번거롭고 어려움
런타임 시점 (Runtime Proxy) - 스프링 AOP

- 자바 main 메서드가 실행된 이후 동작함
- 스프링 컨테이너 + 프록시 + DI + 빈 후처리기를 활용함
- 특별한 컴파일러나 JVM 옵션이 불필요함
- 메서드 실행 지점에만 AOP 적용이 가능 (스프링 빈에만 적용됨)
비교 요약
| 방식 | 부가 기능 삽입 위치 | 필요 설정 | 적용 범위 |
|---|---|---|---|
| 컴파일 시점 | .class 파일 내부 |
AspectJ 컴파일러 | 모든 조인 포인트 |
| 클래스 로딩 시점 | .class 파일 내부 |
-javaagent 옵션 |
모든 조인 포인트 |
| 런타임 시점 (스프링) | 프록시를 통한 위임 | 없음 (스프링만 있으면 됨) | 메서드 실행만 |
AOP 적용 위치 (조인 포인트 범위)
- AspectJ (컴파일/로드 타임)
- 생성자 호출
- 필드 값 접근
- static 메서드 접근
- 메서드 실행
- 스프링 AOP (런타임)
- 메서드 실행만 가능
- 스프링 AOP는 프록시 방식(메서드 오버라이딩)이므로 생성자, static 메서드, 필드 값 접근에는 적용이 불가함
AOP 용어 정리
전체 구조 관계도

용어 정리
| 용어 | 설명 |
|---|---|
| 조인 포인트 (Join point) | AOP를 적용할 수 있는 모든 지점이며, 스프링 AOP는 메서드 실행으로 제한됨 |
| 포인트컷 (Pointcut) | 조인 포인트 중 어드바이스를 적용할 위치를 선별하는 표현식 |
| 타겟 (Target) | 어드바이스를 받는 객체이며 포인트컷으로 결정됨 |
| 어드바이스 (Advice) | 실제 부가 기능 로직이며 Before, After, Around 종류가 존재함 |
| 애스펙트 (Aspect) | 어드바이스 + 포인트컷을 모듈화한 것이며 @Aspect 애노테이션을 사용함 |
| 어드바이저 (Advisor) | 어드바이스 1개 + 포인트컷 1개로 구성되며 스프링 AOP 전용 용어임 |
| 위빙 (Weaving) | 포인트컷으로 선별한 조인 포인트에 어드바이스를 적용하는 행위 |
| AOP 프록시 | AOP 구현을 위해 생성된 프록시 객체이며 JDK 동적 프록시 또는 CGLIB를 사용함 |
연습 문제
-
부가 기능(크로스커팅 관심사)을 여러 곳에 적용할 때 기존 OOP 방식에서 어떤 문제가 발생할까요?
a. 이 모든 문제들이 발생해요.
- 핵심 기능 코드에 부가 기능을 직접 넣으면 코드 중복이 심해지고, 기능을 수정할 때 여러 곳을 고쳐야 하며, 적용 대상을 바꾸기도 어려워짐
- AOP는 이런 복합적인 문제들을 해결하기 위해 등장함
-
AOP는 OOP와 어떤 관계일까요?
a. OOP의 한계를 보완해주는 동반자 같은 역할이에요.
- AOP는 객체 지향 프로그래밍의 부족한 점, 특히 여러 모듈에 흩어져 있는 횡단 관심사(로깅, 트랜잭션 등)를 효과적으로 다루기 위해 나옴
- OOP를 대체하는 것이 아니라 보완하여 더 깔끔한 설계를 돕는 관계임
-
AOP에서 ‘애스펙트(Aspect)’는 무엇과 무엇을 묶어 놓은 모듈일까요?
a. 어드바이스와 포인트컷
- 애스펙트는 어떤 부가 기능(어드바이스)을 어디에 적용할지(포인트컷)를 하나로 모아둔 모듈임
- 스프링 AOP의 핵심 구성 단위라고 할 수 있음
-
스프링 AOP가 부가 기능을 핵심 기능에 연결하는 방식(Weaving)은 주로 무엇을 사용할까요?
a. 프록시 객체를 이용하는 런타임 방식
- 스프링 AOP는 주로 애플리케이션이 실행되는 런타임 시점에 프록시 객체를 동적으로 생성하여 부가 기능을 적용함
- 이 방식 덕분에 원본 자바 코드를 직접 수정하거나 컴파일 시점에 개입하지 않고도 기능을 확장할 수 있음
-
스프링 AOP는 왜 AspectJ처럼 다양한 조인 포인트(예: 생성자, 필드 접근)에 적용하기 어려울까요?
a. AOP 프록시 방식을 사용하기 때문에
- 스프링 AOP는 프록시 패턴을 기반으로 동작하기 때문에 프록시가 가로챌 수 있는 메서드 실행 시점에만 부가 기능을 적용할 수 있음
- 반면 AspectJ처럼 컴파일 타임이나 로드 타임에 바이트코드를 조작하는 방식은 생성자 호출이나 필드 접근 등 더 넓은 범위의 조인 포인트를 지원함
요약 정리
- 부가 기능이 여러 곳에 흩어지면 OOP만으로는 관리하기 어려우며, 이를 해결하기 위해 AOP가 등장함
- AOP는 어드바이스(부가 기능)와 포인트컷(적용 대상)을 하나로 묶은 애스펙트 단위로 모듈화함
- 스프링 AOP는 런타임 프록시 방식으로 동작하며, 별도의 컴파일러나 JVM 옵션 없이 메서드 실행 시점에 부가 기능을 적용함
- 실무에서는 스프링 AOP만으로 대부분의 요구사항을 충족할 수 있으며, 더 넓은 범위의 조인 포인트가 필요한 경우에만 AspectJ를 고려하면 됨