개인/[java] 스프링 입문 공부

AOP란 (AOP를 사용하는 이유, 적용해보기)

hyeley5 2023. 7. 21. 17:29

AOP란? (Aspect Oriented Programming)

- 관점 지향 프로그래밍이라고 불린다.

공통 관심 사항과 핵심 관심 사항을 분리하여 나누어서 보고 그 기준으로 모듈화하여 재사용 할 수 있게 해주는 것
(모듈화 : 어떤 공통된 로직이나 기능을 하나의 단위로 묶는 것)

 

- 공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern) 분리

원하는 곳에 공통 관심 사항을 적용한다.

 

MemberService 에서 회원 조회와 회원가입 시간을 측정해본다.

public List<Member> findMembers() {
    long start = System.currentTimeMillis();

    try {

        return memberRepository.findAll();
    } finally {
        long finish = System.currentTimeMillis();
        long timeMs = finish - start;
        System.out.println("join = " + timeMs + "ms");
    }
}

이런식으로 찍어서 확인해보면

 

 

코드에서 

validateDuplicateMember(member); // 중복 회원 검증

memberRepository.save(member);

return member.getId();

 

이런 등 부분들을 핵심 로직이라 한다. (핵심 관심 사항)

 

시간을 측정하는 로직을 핵심 비즈니스가 아닌 공통 관심 사항이라고 한다.

 

시간 측정 로직과 핵심 비즈니스 로직이 섞여서 유지보수가 어렵다.

 

- 저렇게 일일히  long 입력하고 하는 부분도 그렇고 전체적인 공통 로직을 만들기 매우 어렵다.

- 변경 시에도 모든 로직을 찾아가서 변경해야 한다.

 

AOP 적용 해보기

 

aop 패키지를 만들고

@Aspect
@Component
public class TimeTraceAop {

    @Around("execution(* hello.hellospring1..*(..))")
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        System.out.println("START: " + joinPoint.toString());

        try {
            return joinPoint.proceed();
        } finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("END: " + joinPoint.toString() + " " + timeMs + "ms");

        }
    }
}

@Component 대신에 springconfig 에 등록해서 @Bean 으로 추가하는 방법도 있다.

 

@Around("execution(* 패키지명..*(..))")

 

이전에 일일히 try 안에 두었던 currentTrimeMillis() 삭제해주고,

실행해보면

 

 

이렇게 전체적으로 확인을 할 수 있다.

 

이게 AOP 기능이다.

  • 회원가입, 회원 조회 등 핵심 관심사항과 시간을 측정하는 공통 관심 사항을 분리!
  • 시간을 측정하는 로직 별도의 공통 로직으로 만들었다( TimeTraceAop.java )
  • 회원가입, 회원 조회 등 핵심 관심사항을 깔끔하게 유지 가능.
  • execution 통해서 원하는 적용 대상을 선택할 수 있다.

 

스프링에서 AOP 적용하면

 

기존에 스프링 컨테이너는

memberController -----> memberService 로 가지만

 

AOP를 적용하면 

memberService가 아닌

가짜 memberSercive 를 만들어내어 이쪽으로 간다. (프록시_대리)

 

프록시 기법이 적용됐는지 확인해보려면

memberController 에서

System.out.println("memberService = " + memberService.getClass());

입력하고 실행해보면

 

멤버서비스 뒤에 $$EnhancerBySpringCGLIB$ ··· 

복제를 해서 코드를 조작하는 기술!

 

DI 가 되니까 AOP 가 가능한 것,,  ! 

 

예전에 배웠던 구조에서 확실히 조금 달라진게 느껴진다.

학과생활에서 이렇게 학습을 못하고 쳐내기 바빴던게 정말 아쉽게 느껴진다.ㅠㅠ

 

또 반복반복해서 만들어봐야지 !! 아자잣,,