티스토리 뷰
목차
1. AOP란 무엇인가?
📌AOP의 정의
AOP는 공통된 관심사를 분리하여 핵심 로직과 독립적으로 관리할 수 있도록 하는 프로그래밍 패러다임이다.
🎯AOP가 필요한 이유
OOP(Object-Priented Programming)만으로는 다음 같은 문제를 해결하기 어렵다.
- 로킹, 트랜잭션, 보안 체크, 캐싱, 성능 측정 등은 모든 비즈니스 로직에 반복해서 들어감
- 이러한 횡단 관심사(Cross-cutting concerns)가 중복 코드 유발 + 유지보수 난이도 증가
➡️ AOP는 이 관심사를 핵심 로직에서 분리해 재사용성과 응집도를 높임
🧩 2. AOP 핵심 용어 정리
| 용어 | 설명 |
| Aspect | 횡단 관심사의 모듈화 단위 (클래스) |
| Join Point | Advice가 적용될 수 있는 지점 (ex: 메서드 실행) |
| Advice | Join Point에서 실행되는 코드 (Before, After 등) |
| Pointcut | Advice를 적용할 join Point의 패턴 정의 |
| Weaving | Advice를 실제 코드에 적용하는 과정 (실행 전/후 삽입) |
3. Spring AOP 동작 구조
📌Spring AOP의 핵심 원리 : 프록시 기반
- Spring AOP는 JDK Dynamic Proxy 또는 CGLIB 또는 CGLIB Proxy를 사용하여 프록시 객체를 생성함
- 클라이언트는 프록시를 호출하고, 프록시는 내부에서 실제 대상 메서드 + AOP 로직을 호출함
⚙️ 동작 흐름
[클라이언트]
↓
[프록시 객체] ———> [Advice 실행] → [실제 비즈니스 메서드 호출] → [After Advice]
🔍 AOP 적용 대상
- 기본적으로 Spring Bean에만 적용
- public 메서드만 Pointcut 대상 (Spring AOP는 Proxy 방식이라 제한 있음)
4. Advice 유형별 실전 예제
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service..*(..))")
public void logBefore(JoinPoint joinPoint) {
System.out.println("Before: " + joinPoint.getSignature());
}
@AfterReturning(pointcut = "execution(* com.example.service..*(..))", returning = "result")
public void logAfter(Object result) {
System.out.println("AfterReturning: " + result);
}
@Around("execution(* com.example.service..*(..))")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
Object result = joinPoint.proceed();
long end = System.currentTimeMillis();
System.out.println("Execution Time: " + (end - start) + "ms");
return result;
}
}
예제 설명
- @Before : 메서드 실행 전 로그 출력
- @AfterReturning : 메서드 정상 종료 후 반환값 로깅
- @Around : 전체 흐름 감싸서 실행 시간 측정
🛠️ 5. 실무 적용 사례
| 사례 | AOP 적용 전 | AOP 적용 후 |
| 트랜잭션 처리 | 각 서비스마다 try-catch | @Transactional |
| 로깅 | 모든 메서드에 System.out.println() | @Before, @Around |
| 권한 체크 | 컨트롤러마다 isAdmin() | 커스텀 어노테이션 + @Around |
☑️ Custom Annotation 활용 예시
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AdminOnly { }
@Aspect
@Component
public class AuthAspect {
@Before("@annotation(com.example.annotation.AdminOnly)")
public void checkAdmin() {
// 로그인 유저 권한 체크
}
}
⚠️ 6. 주의할 점 및 한계
- private/protected 메서드에는 AOP 적용 불가
- self-invocation 문제 : 자기 자신 호출에는 AOP 적용되지 않음
- 프록시 기반이므로, 프록시를 우회하는 구조에서는 Advice가 작동하지 않음
7. AOP와 SOLID의 관계
| SOLID 원칙 | AOP 관련성 |
| SRP | 핵심 로직과 공통 기능 분리로 단일 책임 실현 |
| OCP | 공통 기능 확장 시 핵심 로직 건드리지 않음 |
| DIP | 공통 기능을 별도 모듈로 분리하여 구현 의존성 제거 |
| DRY | 중복 로직 제거 (로깅/트랜잭션 등) |
| ISP | 필요 시 특정 기능만 Interface로 모듈화 가능 |
✅ 마무리 요약
- AOP는 로직 간의 관심사 분리를 통해 코드 품질을 높이는 강력한 도구
- 실무에서는 @Transactional, @Async, @Cacheable 등이 모두 AOP의 대표 사례
- AOP는 Spring의 프록시 기반으로 동작하며, 특정 한계가 존재하므로 이해가 필수
'IT > Spring' 카테고리의 다른 글
| ⚠️Spring 예외 처리 완전 정복 - @ControllerAdvice, @ExceptionHandler, 그리고 실무 예외 전략 (0) | 2025.06.18 |
|---|---|
| 🔄 Spring의 @Transactional 완전 정복 - 개념, 원리, 동작 방식, 트러블 슈팅까지 (0) | 2025.06.11 |
| Spring의 DI 방식 완전 정복 - 생성자 / 필드 / 세터 주입, 그리고 언제 어떻게 써야 하는가? (0) | 2025.05.13 |
| Spring Bean과 생명주기 - Bean의 생성부터 소멸까지, 내부에서는 어떤 일이 벌어질까? (0) | 2025.05.12 |
| Spring Framework의 핵심 원리 - IoC, DI, AOP (0) | 2025.05.11 |