AOP

Always·2024년 11월 22일

Backend&Devops

목록 보기
9/15

AOP

AOP란?

  • AOP(Aspect Oriented Programming)은 관점 지향 프로그래밍의 약자로, 프로그래밍 로직을 핵심적인 관심사부가적인 관심사로 나누어 모듈화한다는 의미입니다.
  • 여기서 핵심적인 관심사는 핵심 관심사, 부가적인 관심사는 횡단 관심사(Crosscutting Concerns)라고 불립니다.

  • 핵심 관심사: 서비스 단에서 핵심 비즈니스 로직을 의미합니다.
    예) 데이터 조회, 저장, 삭제 등
  • 횡단 관심사: 여러 비즈니스 로직에 중복으로 들어가면서 강하게 결합된 로직을 의미합니다.
    예) 로깅, 보안, 트랜잭션 관리 등

예제 코드

public class StudentService {
    private final IdentityStudentRepository identityStudentRepository;
    private final SequenceStudentRepository sequenceStudentRepository;
    private int insertNum = 1000;

    public void saveIdentity() {
        for (int i = 0; i < insertNum; i++) {
            System.out.println("save I: " + i);
            identityStudentRepository.save(IdentityStudent.builder()
                    .num(i)
                    .build());
        }
    }

    public void saveSequence() {
        for (int i = 0; i < insertNum; i++) {
            System.out.println("save I: " + i);
            SequenceStudent save = sequenceStudentRepository.save(SequenceStudent.builder()
                    .num(i)
                    .build());
            System.out.println("save id: " + save.getId());
        }
    }
}

문제점

  • 위 코드에서 메서드 실행 전과 실행 후 시간을 출력하여 성능 비교를 하고자 한다면, 실행 시간 측정 코드를 각 메서드에 중복 작성해야 합니다.
  • 이러한 중복된 코드들은 핵심 로직(저장 로직)과 강하게 결합되어 있어 코드의 분리가 어렵고 유지보수성이 떨어집니다.

AOP 적용 효과

  • AOP를 사용하면 중복된 코드를 제거하고, 횡단 관심사 코드를 한 곳에 모아 응집도를 높일 수 있습니다.
  • 이를 통해 핵심 로직과 부가 로직을 분리하여 OOP의 설계 원칙을 더욱 잘 실현할 수 있습니다.


AOP 용어

1. Target

  • 부가기능을 적용할 대상
    • 예) 특정 메서드, 객체, 클래스

2. Advice

  • 부가기능을 모듈화한 코드
    • "어떤 시점에 어떤 기능을 실행할지"를 정의

3. Join Point

  • Advice가 적용될 수 있는 실행 지점
    • 예) 메서드 실행 전, 실행 후 (Spring AOP에서는 메서드 실행 단계)

4. Pointcut

  • Advice를 적용할 Join Point를 선별하는 작업
    • 예) 특정 메서드나 클래스만 선택적으로 적용

5. Advisor

  • Pointcut과 Advice를 포함하는 객체
    • 예) "어떤 기능을, 어느 시점에, 어떤 메서드에 적용할지"를 결정

6. Weaving

  • Join Point에 Advice를 적용하는 과정
    • Spring AOP에서는 Runtime Weaving을 사용하여 애플리케이션 실행 시 프록시 객체를 생성합니다.

스프링 AOP 동작 방식

  • Spring AOP는 프록시 패턴을 기반으로 동작합니다.

동작 흐름

  1. 클라이언트가 메서드를 호출하면, 프록시 객체가 이를 가로챕니다.
  2. 프록시는 Advice를 실행합니다.
  3. Advice 실행 후 타깃(Target) 메서드를 호출합니다.
  4. 타깃 메서드 실행 결과를 다시 프록시가 받아, 클라이언트에게 반환합니다.

프록시 객체 생성 과정

  • Runtime Weaving은 Spring AOP의 핵심으로, 프록시 객체를 생성합니다.
  • 프록시 객체 생성은 Spring의 BeanPostProcessor를 이용하여 다음 순서로 진행됩니다:
  1. 객체가 생성된 후, 빈 후처리기(BeanPostProcessor)로 전달됩니다.
  2. Advisor의 Pointcut을 통해 해당 객체가 AOP 대상인지 판별합니다.
  3. AOP 대상이라면 프록시 객체를 생성하여 반환합니다.
  4. 그렇지 않다면 원래 객체를 그대로 반환합니다.
  5. 프록시 또는 원래 객체가 Spring 컨테이너에 등록됩니다.

AOP 적용 방법

커스텀 어노테이션 사용

스프링 AOP를 적용할 때, 커스텀 어노테이션을 사용하면 특정 메서드에 유연하게 AOP를 적용할 수 있습니다.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface TimeTrace {
}

### Aspect 클래스 구현

```java
@Log4j2
@Component
@Aspect
public class TimeTraceAspect {

    // Pointcut: AOP를 적용할 범위 설정
    @Pointcut("@annotation(com.example.Aop.TimeTrace)")
    private void timeTracePointcut() {
    }

    // Around Advice: 실행 전후로 부가기능 실행
    @Around("timeTracePointcut()")
    public Object traceTime(ProceedingJoinPoint joinPoint) throws Throwable {
        StopWatch stopWatch = new StopWatch();
        try {
            stopWatch.start();
            return joinPoint.proceed(); // 실제 타깃 메서드 호출
        } finally {
            stopWatch.stop();
            log.debug("{} - Total time = {}s",
                    joinPoint.getSignature().toShortString(),
                    stopWatch.getTotalTimeSeconds());
        }
    }
}

설명

  1. @TimeTrace: AOP가 적용될 메서드에 붙이는 커스텀 어노테이션.

    • @Target: 어노테이션이 적용될 대상(여기서는 메서드).
    • @Retention: 어노테이션 유지 시점(런타임).
  2. TimeTraceAspect: AOP 로직을 구현하는 클래스.

    • @Pointcut: AOP를 적용할 범위를 정의합니다. 위에서는 @TimeTrace 어노테이션이 붙은 메서드만 적용됩니다.
    • @Around: Advice의 일종으로, 메서드 실행 전후에 부가기능을 실행합니다.
    • ProceedingJoinPoint: AOP 대상 메서드 호출 컨텍스트로, 실제 메서드를 호출하기 위해 사용됩니다.

AOP 적용 결과

  • 중복 코드 제거: 부가기능을 한 곳에 모아 관리할 수 있습니다.
  • 핵심 로직과 부가기능의 분리: 비즈니스 로직과 횡단 관심사를 분리하여 코드의 가독성과 유지보수성을 높입니다.
  • OOP 강화: 모듈화된 설계를 통해 객체 지향 프로그래밍의 원칙을 더 잘 실현합니다.

참고자료: https://www.youtube.com/watch?v=7BNS6wtcbY8

profile
🐶개발 블로그

0개의 댓글