Spring Boot/Spring Boot 입문 강의 정리(김영한)

[SpringBoot-스프링 입문] 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술: 7. AOP

조찬국 2024. 2. 22. 02:04
728x90

강의 출처:https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%EC%9E%85%EB%AC%B8-%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8

해당 강의는 Inflearn에 등록된 김영한님의 Springboot 강의입니다.

 

 

이번 장에는 AOP에 대해서 설명하겠다.

1. AOP가 필요한 상황

위의 이미지와 같이 각 컴포넌트별 성능을 측정하기 위해 시간측정 로직을 추가한다고 가정하자.
성능은 데이터 베이스에서 조회 되어 return 할때까지로 측정하겠다.

 

@Transactional
public class MemberService {

//...SpringDataJpaMemberRepository와 MemberService 의존관계(생성자 주입)는 생략했습니다.

/**
 * 회원 조회 시간 측정 추가
 */
    //회원가입
    public Long join(Member member)
    {
        long start = System.currentTimeMillis();
        try {
            validateDuplicateMember(member); //중복 회원 검증
            springDataJpaMemberRepository.save(member);
            return member.getId();
        }
        finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("join " + timeMs + "ms");
        }
    }
    //전체회원 조회
    public List<Member> findMembers()
    {
        long start = System.currentTimeMillis();
        try {
            return springDataJpaMemberRepository.findAll();
        }
        finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("findMembers " + timeMs + "ms");
        }
    }
}

위 코드의 문제

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

한 번 테스트 해보자.

콘솔창에서 쿼리 및 시간 측정 로직 확인

스프링 데이터 JPA는 영속성 컨텍스트를 관리하여 엔티티의 상태를 추적한다. 두 번째 조회에서는 이미 영속성 컨텍스트에 해당 엔티티가 존재하므로 데이터베이스에 다시 접근할 필요 없이 영속성 컨텍스트에서 엔티티를 가져오므로 속도가 빨라질 수 있다. 우선 이정도만 알아두고 추후 설명하겠다.

2. AOP 적용

AOP(Aspect-Oriented Programming): 는 프로그래밍에서 관심사(Concern)를 모듈화하는 방법 중 하나로, 핵심 기능공통 기능을 분리하여 개발하는 방법론이다.

hello/hellospring/aop 디렉토리에 생성

@Aspect
@Component //스프링빈으로 등록.
public class TimeTraceAop {
    //★★★패키지 전체에 적용. 띄워쓰기 잘해야함!!★★★
    @Around("execution(* hello.hellospring..*(..))")
    //@Around("execution(* hello.hellospring.service..*(..))") //:service 하위에 있는 애들만 적용
    public Object excute(ProceedingJoinPoint joinPoint) throws Throwable{
        long start = System.currentTimeMillis();
        System.out.println("START: "+joinPoint.toString());
        try {
            Object result = joinPoint.proceed();//다음 메소드로 받을 수 있다
            return  result;
        } finally {
            long finish=System.currentTimeMillis();
            long timeMs=finish-start;
            System.out.println("END: "+joinPoint.toString()+" "+timeMs+"ms");
        }
    }
}

콘솔창에서 쿼리 및 AOP적용 확인

임의로 test1을 등록했다. AOP를 적용하고 나니 각 컴포넌트 별 시간을 측정할 수 있었다.

AOP적용으로 인해 위 코드의 시간 측정에 대해 다음과 같이 해결 할 수 있다.

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

3. AOP 동작 원리

AOP 적용 전 의존관계

AOP 적용 후 의존관계

AOP 적용 전 전체 그림

AOP 적용 후 전체 그림

 

 

실제 프록시가 동작하는지 확인

728x90