Hi yoahn 개발블로그

[Spring] #8 AOP 본문

Framework & Library/springboot

[Spring] #8 AOP

hi._.0seon 2021. 1. 29. 19:43
반응형

1. AOP가 필요한 상황

AOP, Aspect Oriented Programming. 관점 지향 프로그래밍

- 어떤 로직을 기준으로 핵심적인 관점 & 부가적인 관점으로 나누어서 보고 그 관점을 기준으로 각각 모듈화

- 모듈화: 어떤 공통된 로직이나 기능을 하나의 단위로 묶는 것

 

소스 코드에서 여러 부분에서 반복해서 쓰는 코드들 : 흩어진 관심사

흩어진 관심사를 Aspect로 모듈화 하고 핵심적인 비즈니스 로직에서 분리하여 재사용하겠다는 것이 AOP의 취지

 

ex) 함수 호출 시간 측정

public class MemberService {

    private final MemberRepository memberRepository;

    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    /**
     * 회원 가입
     */
    public Long join(Member member) {
        long start = System.currentTimeMillis();
        try {
            // 같은 이름이 있는 중복 회원 X
            validateDuplicateMember(member); // 중복 회원 검증
            memberRepository.save(member);
            return member.getId();
        } finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("join = " + timeMs + "ms");
        }
    }

    private void validateDuplicateMember(Member member) {
        memberRepository.findByName(member.getName())
                .ifPresent(m -> {
                    throw new IllegalStateException("이미 존재하는 회원입니다");
                });
    }

    /**
     * 전체 회원 조회
     */
    public List<Member> findMembers() {
        long start = System.currentTimeMillis();
        try {
            return memberRepository.findAll();
        } finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("findMembers = " + timeMs + "ms");
        }
    }
    ..
}

-> 변경이 필요할 때마다 메서드 각각 다 변경해 주어야 함

 

문제

  • 회원가입, 회원 조회에 시간을 측정하는 기능은 핵심 관심 사항이 아니다.
  • 시간을 측정하는 로직은 공통 관심 사항이다.
  • 시간을 측정하는 로직과 핵심 비즈니스의 로직이 섞여서 유지보수가 어렵다.
  • 시간을 측정하는 로직을 별도의 공통 로직으로 만들기 매우 어렵다.
  • 시간을 측정하는 로직을 변경할 때 모든 로직을 찾아가면서 변경해야 한다.

2. AOP 적용

반복되는 작업을 줄이기 위해 AOP 적용

공통 관심 사항 VS 핵심 관심 사항 분리

AOP

스프링 빈 등록 방법

1. @Bean 으로 직접 등록

2. @Component 로 등록

 

hello.hellospring.aop/TimeTraceAop.java

@Aspect
//@Component
public class TimeTraceAop {

    @Around("execution(* hello.hellospring..*(..))")
    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");
        }
    }
}

Spring Bean 직접 코드로 등록

@Configuration
public class SpringConfig {
...
    @Bean
    public TimeTraceAop timeTraceAop() {
        return new TimeTraceAop();
    }
}

@Around("execution(* hello.hellospring..*(..))")

- Aop 를 [hello.hellospring] 패키지 아래에 있는 것들의 모든 클래스, 파라미터 타입에 적용

- 패키지 하위의 모든 것에 AOP 적용

 

@Around("execution(* hello.hellospring.service..*(..))")

- service 패키지 하위에 있는 것들에 적용

 

해결

  • 회원가입, 회원 조회등 핵심 관심사항과 시간을 측정하는 공통 관심 사항을 분리한다.
  • 시간을 측정하는 로직을 별도의 공통 로직으로 만들었다.
  • 핵심 관심 사항을 깔끔하게 유지할 수 있다.
  • 변경이 필요하면 이 로직만 변경하면 된다.
  • 원하는 적용 대상을 선택할 수 있다.

 

AOP 적용 전
AOP 적용 후

적용 전

Controller 가 memberService 호출

 

적용 후

스프링 빈에 등록할 때 AOP가 지정된 것의 프록시를 만들어 놓고 (가짜 memberService) 실제 클래스 전에 프록시를 호출하고, joinPoint.proceed() 함수를 통해서 실제 memberService를 호출

-> 컨트롤러가 프록시(가짜 memberService) 호출

 

 

AOP 타겟이 전체로 설정된 경우

AOP 적용 전
AOP 적용 후

 

ref.

engkimbs.tistory.com/746

 

[Spring] 스프링 AOP (Spring AOP) 총정리 : 개념, 프록시 기반 AOP, @AOP

| 스프링 AOP ( Aspect Oriented Programming ) AOP는 Aspect Oriented Programming의 약자로 관점 지향 프로그래밍이라고 불린다. 관점 지향은 쉽게 말해 어떤 로직을 기준으로 핵심적인 관점, 부가적인 관점으..

engkimbs.tistory.com

inflearn.com

스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술

 

 

반응형
Comments