-
[Spring] AOP 알아보기 - Spring AOP의 특징Spring 2025. 12. 27. 16:19
1. Spring AOP의 기술적 특징
"순수 자바로 구현되었으며, 특별한 설정이 필요 없습니다."
- Pure Java: Spring AOP는 순수 자바로 구현되어 있습니다.
- 핵심 원리 (프록시 패턴): Spring AOP의 핵심은 "동적 프록시(Dynamic Proxy)"입니다.
- Spring은 내부적으로 자바 표준 라이브러인 java.lang.reflect.Proxy (인터페이스 기반)나, 오픈소스 라이브러리인 CGLIB (클래스 상속 기반)를 사용하여 런타임에 가짜 객체(Proxy)를 만들어냅니다.
- 이 모든 과정이 표준 Java 언어 스펙 안에서 이루어지기 때문에, Java가 돌아가는 어떤 환경에서든 똑같이 동작합니다.
- 핵심 원리 (프록시 패턴): Spring AOP의 핵심은 "동적 프록시(Dynamic Proxy)"입니다.
- Spring AOP는 C++ 같은 네이티브 코드를 쓰거나, 복잡한 외부 JVM 에이전트를 강제하지 않습니다. 오직 표준 Java API만을 사용하여 구현되었습니다.
- No Special Compilation: 별도의 컴파일 과정이 필요 없습니다.
- AspectJ의 방식 (Compile-time Weaving):
- AspectJ는 소스 코드를 컴파일할 때, 특수한 컴파일러(ajc)를 사용해야 합니다.
- 이 컴파일러가 .java 파일을 .class로 바꿀 때, AOP 로직(Advice)을 바이트코드 사이에 직접 끼워 넣습니다.
- 단점: 빌드 설정(Maven/Gradle)이 복잡해지고, IDE 설정도 까다로울 수 있습니다.
- Spring AOP의 방식 (Runtime Weaving):
- 우리가 쓰는 일반적인 자바 컴파일러(javac)로 평범하게 컴파일합니다.
- 언제 적용되나? 애플리케이션이 실행되고(Runtime), Spring 컨테이너가 Bean을 생성하는 시점에 프록시 객체를 통해 AOP를 적용합니다.
- 장점: 개발자는 평소처럼 개발하고 빌드하면 됩니다. 빌드 스크립트를 뜯어고칠 필요가 없습니다.
- AspectJ의 방식 (Compile-time Weaving):
- 클래스 로더 제어 불필요: 클래스 로더 계층 구조를 제어할 필요가 없으므로, 서블릿 컨테이너나 애플리케이션 서버 환경에서 사용하기에 매우 적합합니다.
- 문제 상황 (Load-Time Weaving의 어려움):
- 일부 강력한 AOP 기능(Load-Time Weaving)을 쓰려면, 클래스가 JVM 메모리에 로딩되는 시점에 바이트코드를 조작해야 합니다.
- 이를 위해서는 전용 ClassLoader를 쓰거나 Java Agent(javaagent 옵션)를 설정해야 합니다.
- 하지만 Tomcat, JBoss, WebLogic 같은 서블릿 컨테이너나 WAS는 이미 자신만의 복잡한 ClassLoader 계층 구조를 가지고 있습니다. 여기에 외부 AOP 기술이 끼어들려고 하면 충돌이 나거나 설정이 매우 복잡해집니다.
- Spring AOP의 해결책:
- Spring AOP는 클래스 로딩 과정에 관여하지 않습니다.
- 이미 로딩이 다 끝난 객체를 대상으로 프록시를 씌우기 때문입니다.
- 결과: 톰캣이든, 제티든, 어떤 WAS를 쓰든 환경을 타지 않고 안정적으로 동작합니다.
- 문제 상황 (Load-Time Weaving의 어려움):
- 이 특징은 웹 애플리케이션 서버(WAS) 환경에서 매우 중요합니다.
2. 지원 범위와 한계
"오직 메서드 실행 시점만 지원합니다."
- Method Execution Only: Spring AOP는 현재 메서드 실행 조인 포인트(Method Execution Join Points) 만 지원합니다. 즉, Spring Bean에 있는 메서드를 실행할 때만 끼어들 수 있습니다.
- 필드 가로채기 불가: 멤버 변수(Field)에 접근하거나 값을 수정하는 행위는 가로챌 수 없습니다.
- Tip: 만약 필드 접근을 제어하거나, 업데이트하는 시점에 로직을 넣어야 한다면 AspectJ 언어를 사용해야 합니다.
3. Spring AOP의 목표와 철학
"완벽한 AOP가 아니라, Spring IoC와 완벽하게 통합된 AOP를 지향합니다."
- 완전함보다 실용성: Spring AOP는 가장 완벽한 AOP 기능을 제공하는 것을 목표로 하지 않습니다.
- 문제 해결: 대신, AOP 구현과 Spring IoC(제어의 역전) 컨테이너 간의 긴밀한 통합을 통해 엔터프라이즈 애플리케이션의 일반적인 문제(트랜잭션, 보안 등)를 해결하는 것을 목표로 합니다.
- Bean 기반 구성: Aspect도 일반적인 Bean 정의 문법을 사용하여 구성합니다. 이는 다른 AOP 프레임워크와 구별되는 Spring만의 특징입니다.
4. Spring AOP vs AspectJ (경쟁이 아닌 상호보완)
"도메인 객체 같은 세밀한 제어는 AspectJ, 일반적인 서비스는 Spring AOP"
- Spring AOP가 힘든 경우: 매우 세밀한 객체(주로 도메인 객체, new로 생성하는 객체들)에 AOP를 적용하는 것은 Spring AOP로는 어렵거나 비효율적입니다. 이런 경우에는 AspectJ가 최고의 선택입니다.
- 상호 보완: Spring 팀은 Spring AOP(프록시 기반)와 AspectJ(완전한 AOP)가 서로 경쟁 관계가 아니라 상호 보완적이라고 봅니다.
- 통합: Spring은 이 두 가지를 매끄럽게 통합하여 지원하므로, 개발자는 상황에 맞춰 두 기술을 모두 활용할 수 있습니다.
5. 비침습성(Non-invasiveness)과 선택권
"비즈니스 로직을 더럽히지 않는 것이 원칙이지만, 편의를 위한 선택권도 줍니다."
- 비침습성 원칙: 비즈니스나 도메인 모델에 프레임워크 특정 클래스나 인터페이스를 강제로 도입하지 않는 것이 Spring의 핵심 신조입니다.
- 실용적 선택: 하지만 때로는 프레임워크 의존성을 도입하는 것이 코드를 읽거나 작성하기 훨씬 쉬울 때가 있습니다. Spring은 이럴 때 선택권을 줍니다.
- 스타일 선택:
- AspectJ vs Spring AOP: 무엇을 쓸지 선택 가능
- @AspectJ (어노테이션) vs XML 스키마: 설정 방식 선택 가능
구분 Spring AOP AspectJ
적용 시점 런타임 (프록시) 컴파일 타임, 로드 타임 (바이트코드 조작) 적용 대상 Spring Bean (컨테이너가 관리하는 객체) 모든 객체 (Spring이 관리 안 하는 도메인 객체 포함) 조인 포인트 메서드 실행만 가능 메서드, 생성자, 필드 접근 등 다양함 성능 약간의 오버헤드 있음 (일반적으론 무시 가능) 컴파일 시 코드가 삽입되므로 더 빠름 복잡도 낮음 (별도 설정 불필요) 높음 (별도 컴파일러나 에이전트 필요) 결론 대부분의 엔터프라이즈 문제 해결에 충분함 Spring AOP로 해결 안 되는 고급 기능 필요 시 사용 'Spring' 카테고리의 다른 글
[Spring] AOP 알아보기 - Spring AOP 프록시 매커니즘 (1) 2025.12.27 [Spring] AOP 알아보기 - AOP 개념 (0) 2025.12.27 [Spring] AOP 알아보기 - AOP 소개 (0) 2025.12.27 [Spring] 서비스(Service) 레이어의 본질적인 역할과 책임 (0) 2025.12.20 [스프링] 안티패턴: 완화된 레이어드 아키텍처 (0) 2025.12.19 - Pure Java: Spring AOP는 순수 자바로 구현되어 있습니다.