[Spring] 스프링 입문(코드로 배우는 스프링 부트, 웹, MVC, DB 접근 기술) 강의 정리 - 6

JJAM·2022년 8월 16일
0
post-thumbnail
  • 해당 게시물은 인프런 - "스프링 입문 - 코드로 배우는 스프링 부트, 웹, MVC, DB 접근 기술" 강의를 참고하여 작성한 글 입니다.
  • 공부하는 입장이라 내용이 부실할 수 있으며 공부한 내용 정리하기 위한 용도로 작성한 게시물 입니다.
  • 초보자이므로 내용에 있어 미숙하며, html css javascript를 할 수 있는 상태에서 작성한 글 입니다.
    강의 링크 -> 김영한 - 스프링 입문 (무료강의)

📖 AOP

📒 AOP가 필요한 상황

🖋️ AOP가 필요한 상황

  • 모든 메소드의 호출 시간을 측정하고 싶을 때
  • 공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern)
  • 회원 가입 시간, 회원 조회 시간을 측정하고 싶을 때

🖋️ MemberService 회원 조회 시간 측정

회원 가입 시간을 측정해보기 위한 코드를 작성한다.

src/main/java/spring.study1/service/MemberService

package spring.study1.service;

...

@Transactional
public class MemberService {
	...

    // 회원가입
    public Long join(Member member) {

        // 시작할 때 시간 측정
        long start = System.currentTimeMillis();

        try {
            // 이름이 같은 중복 회원 X
            validateDuplicateMember(member);

            // member를 저장소에 저장
            memberRepository.save(member);
            return member.getId();
            
        } finally { // try가 끝날 때 실행하는 동작
        
        	// 끝날 때 시간 측정
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("timeMS : "+ timeMs + "ms");
        }
    }
	...
}

다음과 같이 회원가입을 하는 데 걸리는 시간을 출력해주는 코드를 작성하고 이를 확인하기 위해 Test코드를 실행하면 아래와 같이 소요시간이 나온다.

회원가입 뿐만 아니라 다른 기능을 실행할 때 걸리는 시간을 측정하기 위해 위에 코드처럼 try~finally 코드를 작성해야 한다. 하지만 이렇게 코드를 작성하면 많은 문제들이 발생한다.

🖋️ 시간 측정 문제점

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

이러한 문제점들을 해결하기 위해 AOP를 사용해야 한다.


📒 AOP 적용

🖋️ AOP 설명

AOP

  • Aspect Oriented Programming
  • 공통 관심 사항(cross-cutting concern) vs 핵심 관심 사항(core concern) 분리
  • 원하는 곳에 공통 관심 사항 적용

🖋️ 시간 측정 AOP 등록

시간을 측정하는 AOP를 만들기 위해 새로운 패키지와 파일을 만든다.

src/main/java/spring.study1/apo/TimeTraceAop

package spring.study1.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class TimeTraceAop { 
    
    @Around("execution(* spring.study1..*(..))") // AOP를 사용할 위치(spring.study1 하위 모든 메서드)
    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");
        }
    }
}

AOP를 사용하기 위해 Component scan 방식으로 Spring Bean에 등록 했는데, 이 외에도 직접 Spring Bean에 등록하는 방법이 있다.

src/main/java/spring.study1/SpringConfig

package spring.study1;
...

@Configuration
public class SpringConfig {
	...
    // Spring bean에 TimeTraceAop 등록
    @Bean
    public TimeTraceAop timeTraceAop() {
        return new TimeTraceAop();
    }
}

🖋️ 시간 측정 AOP 실행

시간 측정 AOP 코드를 작성후 실행을 하면 아래 사진처럼 메서드마다 실행 시간을 알 수 있게 된다.

AOP를 사용하게 되면서

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

🖋️ 스프링의 AOP 동작 방식

AOP를 적용하면, 가짜 memberService라는 프록시를 만들고 진짜 memberService 앞에 가짜 memberServicespring bean으로 등록한다.
가짜 memberService가 종료되면 joinPoint.proceed() 를 통해 실제 memberService를 호출해단다.
그래서 memberController가 호출해주는 건 진짜 memberService가 아니라 가짜 memberService 이다.


지금까지 "김영한 - 스프링 입문 (무료강의)" 강의를 참고하여 스프링 웹 개발 기초에서 AOP 에 대해 공부하였다.

profile
☘️

0개의 댓글