kimgusxo 님의 블로그
4. 관점 지향 프로그래밍(Aspect-Oriented Programming, AOP) 본문
1. AOP란?
.
- "관점 지향 프로그래밍"으로 핵심 로직 외의 반복되는 부가 기능(cross cutting concerns)을 공통된 영역(aspect)으로 분리해서 관리하는 프로그래밍 패러다임이다.
- 로그 남기기, 트랜잭션 처리, 시간 측정 등에 사용된다.
1-1. 기존 방식 문제점
public class MemberService {
public void join(Member member) {
long start = System.currentTimeMillis();
try {
repository.save(member);
} finally {
long end = System.currentTimeMillis();
System.out.println("수행 시간 = " + (end - start));
}
}
}
- 핵심 로직(join)에 시간 측정이라는 부가기능이 섞여있음
- 다른 메소드에도 복사/붙여넣기 반복함
- 유지보수 시 모든 메소드를 수정해야한다. (OOP 원칙 위배)
1-2. AOP 방식
@Service
public class MemberService {
public void join() {
System.out.println("회원 가입 로직 실행");
}
}
@Aspect
@Component
public class TimeTraceAspect {
@Around("execution(* com.example..*(..))")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
System.out.println("시작: " + joinPoint.getSignature());
try {
return joinPoint.proceed(); // 실제 대상 메서드 호출
} finally {
long end = System.currentTimeMillis();
System.out.println("종료: " + joinPoint.getSignature());
System.out.println("수행 시간: " + (end - start) + "ms");
}
}
}
- 동작 흐름: 클라이언트 호출 -> 프록시 객체(TimeTraceAspect) -> 실제 MemberService 실행
- join()을 호출하면 프록시가 먼저 동작해서 시간 측정을 하고 원래 로직을 실행한 후 종료 로깅까지 처리
- execution(* com.example..*(..))
- 패키지와 그 하위 모든 클래스의 모든 메소드에 적용한다는 뜻
- *(..): 모든 메소드 이름 + 모든 파라미터
- 핵심 비즈니스 로직은 그대로 유지함
- 부가기능(공통기능)은 완전히 별도 클래스에서 관리
- 스프링이 자동으로 핵심 로직의 앞/뒤로 프록시를 삽입하여 실행시킨다
2. AOP 주요 개념
Aspect | 공통 기능 (ex. 시간 측정, 로그 출력 등) |
Advice | 언제 실행할지 (before, after 등) |
JoinPoint | Advice가 적용될 수 있는 지점 (메소드 실행 시점 등) |
PointCut | Advice가 적용될 대상 조건 (어떤 클래스의 어떤 메소드인지?) |
Target | 실제 비즈니스 로직 객체 |
Proxy | AOP 기능이 적용된 객체 |
Weaving | Aspect를 핵심 로직에 삽입하는 과정 |
3. 스프링 AOP의 내부 구조
- 개발자가 @Aspect 클래스 작성
- 스프링이 해당 Aspect를 인식하여 Proxy 객체 생성
- 핵심 로직 실행 전/후로 Advice 삽입
- 개발자는 핵심 코드만 작성 -> 나머지는 자동으로 처리됨
4. AOP 어노테이션
@Aspect | 이 클래스가 AOP 기능을 가진다는 표시 |
@Around(...) | 메소드 실행 전/후로 Advice 실행 |
@Before | 메소드 실행 전에만 Advice 실행 |
@After | 메소드 실행 후에만 Advice 실행 |
@AfterReturning | 메소드 정상 종료 후 Advice 실행 |
@AfterThrowing | 예외 발생 시 Advice 실행 |
@PointCut | 여러 Advice에서 재사용할 조건 정의 |
@EnableAspectJAutoProxy | Spring에서 AOP 기능을 활성화 (SpringBoot에서는 자동으로 활성화된다.) |
5. 주의 사항
- 클래스에 final을 붙이면 CGLIB 프록시가 적용되지 않는다.
- private 메소드는 AOP 적용이 불가능하다.
- @Around 내부 표현식을 정확히 적어야 한다.
- AOP는 빈으로 등록된 클래스만 적용됨 (스프링 컨테이너 외 객체는 제외된다.)
'BackEnd > Spring' 카테고리의 다른 글
6. 서블릿(Servlet) (0) | 2025.06.16 |
---|---|
5. 트랜잭션(Transaction) (0) | 2025.06.08 |
3강. 빈(Bean) 생명 주기(생성~소멸) (0) | 2025.05.16 |
2강. 빈(Bean)과 컴포넌트 스캔(ComponentScan) (0) | 2025.05.07 |
1강. 제어의 역전(IoC)과 의존성 주입(DI) (1) | 2025.05.07 |