Notice
Recent Posts
Recent Comments
Link
«   2025/07   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Tags more
Archives
Today
Total
관리 메뉴

kimgusxo 님의 블로그

4. 관점 지향 프로그래밍(Aspect-Oriented Programming, AOP) 본문

BackEnd/Spring

4. 관점 지향 프로그래밍(Aspect-Oriented Programming, AOP)

kimgusxo 2025. 5. 30. 22:41

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는 빈으로 등록된 클래스만 적용됨 (스프링 컨테이너 외 객체는 제외된다.)