스프링 입문 맛보기 10

Spring 정리 2021. 8. 11. 13:04

인프런 강의 18일차.

 - 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 (김영한 강사님)

 

1. AOP가 필요한 상황

 - 모든 메소드의 호출 시간을 측정하고 싶다면?

 - 공통 관심 사항(Cross-cutting concern) vs 핵심 관심 사항(core concern)

 - 회원가입시간, 회원조회시간을 측정하고 싶다면?

 - 메소드 실행 때 인터셉트해서 컨트롤할 수 있는 것!

 

 * MemberService 회원 조회 시간 측정 추가

@Transcational
public class MemberService {

	//회원가입
    public Long join(Member member){
		long start = System.currentTimeMillis();
        
        try{
        	validateDuplicatieMember(member);	//중복회원검증
            memberRepository.save(member);
            return member.gerId();
        } 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 memberRepository.findAll();
        } finally {
			long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("join = " + timeMs + "ms");
		}
	}
}

 ** 문제

    - 회원가입, 회원조회에 시간을 측정하는 기능은 핵심관심사항이 아니다.

    - 시간을 측정하는 로직은 공통 관심사항이다.

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

    - 시간을 측정하는 로직을 별도 공통로직으로 만들기 매우 어렵다.

    - 시간을 측정하는 로직을 변경할 때 모든 로직을 찾아가면서 변경해야한다.

 

2. AOP 적용

 - AOP : Aspect Oriented Programming

 - 공통관심사항과 핵심관심사항 분리

 * 시간 측정 AOP 등록

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.sterotype.Component;

@Component		//Component 스캔되도록 annotation선언해도 되지만 Spring Bean에 직접 등록해주는게 좋다
@Aspect
public class TimeTraceApp {

	//Around : AOP를 적용할 영역 지정
	@Around("execution(* hello.hellospring..*(..))")	//hellospring package 하위 전부 적용한다는 의미
	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");
		}
	}
}


//TimeTraceAop.java 에 Bean 선언
@Bean
public TimeTraceAop timeTraceAop() {
	return new TimeTraceAop();
}

 ** 해결

    - 회원가입, 회원조회 등 핵심관심사항과 시간을 측정하는 공통관심사항을 분리한다.

    - 시간을 측정하는 로직을 별도의 공통 로직으로 만들었다.

    - 핵심관심사항을 깔끔하게 유지할 수 있다.

    - 변경이 필요하면 이 로직만 변경하면 된다.

    - 원하는 적용 대상을 선택할 수 있다.

 

3. AOP 동작 방식

 - AOP 적용 전 의존관계 : helloContainer -> memberService 호출

 - AOP 적용 후 의존관계 : helloContainer -> | (Proxy)memberService | -> 실제 memberService

 - Proxy 역할을 하는 memberSerivece가 생성됨. proxy는 joinPoint.proceed()를 호출하여 실제 memberService를 호출함.

 - Around가 적용되는 것 만큼 ProxyController, ProxyService, ProxyRepository가 생성됨.