본문 바로가기

Spring

AOP를 활용한 Logging 구현

AOP(Aspect Oriented Programming)

AOP는 관점 지향 프로그래밍이라고 해석할 수 있습니다. 비즈니스 로직의 기준을 정하고 그 기준에 따라 나눈 부분을 관점이라고 한다면, 이 관점을 모듈화 하는 것입니다.

AOP의 용어

Aspect : 여러 클래스에서 중복적으로 사용되는 공통된 관점을 모듈화 한 것
Joinpoint : method 또는 excepition와 같은 끼어들 수 있는 지점
Pointcut : 특정 Joinpoint에서 Aspect가 적용할 Advice를 일치시키기 위한 것
Advice:  특정 Joinpint에서 Aspect가 한 액션입니다.
Target : Aspect를 적용하는 지점

Logging 구현

실제 서비스에서 로그를 남기는 것은 선택이 아닌 필수입니다. 로그를 남겨서 에러가 발생하였을 때, 즉각적으로 대처할 때 주요할 것이며, 실제 내가 작성한 코드의 흐름이 정상적으로 동작하고 있는지에 대한 판단 여부에도 많은 도움이 될 수 있습니다. 물론 이외에도 여러 가지 이유가 있을 수 있습니다!

1. 의존성 추가

Spring boot에서 AOP를 사용하기 위해서는 의존성을 추가해줘야 합니다. maven을 빌드 툴로 프로젝트를 생성했기 때문에 pom.xml에 아래와 같이 추가해줍니다.

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. EnableAspectJAutoProxy 추가

    @EnableAspectJAutoProxy // AOP 사용
    @SpringBootApplication
    public class BeApplication {
        public static void main(String[] args) {
            SpringApplication.run(BeApplication.class, args);
        }
    }

3. LogAspect.class 생성

Aspect 어노테이션을 추가하여 이 클래스가 공통된 관점을 모듈화한 Aspect라는 것을 명시합니다. 그리고 Component 어노테이션을 추가하여 Bean으로 등록해줍니다.

@Around를 사용하여 method를 target으로 지정하여 com.ecommerce.be 패키지 아래 객체의 모든 method에 Aspect를 적용합니다. 

@Aspect
@Component
public class LogAspect {

    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    @Around("within(com.ecommerce.be..*)")
    public Object logging(ProceedingJoinPoint pjp) throws Throwable {

        String params = getRequestParams();

        long startAt = System.currentTimeMillis();

        logger.info("----------> REQUEST : {}({}) = {}", pjp.getSignature().getDeclaringTypeName(),
                pjp.getSignature().getName(), params);

        Object result = pjp.proceed();

        long endAt = System.currentTimeMillis();

        logger.info("----------> RESPONSE : {}({}) = {} ({}ms)", pjp.getSignature().getDeclaringTypeName(),
                pjp.getSignature().getName(), result, endAt-startAt);

        return result;

    }

    // get requset value
    private String getRequestParams() {

        String params = "";

        RequestAttributes requestAttribute = RequestContextHolder.getRequestAttributes();

        if(requestAttribute != null){
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder
                    .getRequestAttributes()).getRequest();

            Map<String, String[]> paramMap = request.getParameterMap();

            if(!paramMap.isEmpty()) {
                params = " [" + paramMapToString(paramMap) + "]";
            }
        }
        return params;
    }

    private String paramMapToString(Map<String, String[]> paramMap) {
        return paramMap.entrySet().stream()
                .map(entry -> String.format("%s -> (%s)",
                        entry.getKey(), Joiner.on(",").join(entry.getValue())))
                .collect(Collectors.joining(", "));
    }
}

4. ApiController.class

간단한 컨트롤러를 만들어 봅니다.

@RequiredArgsConstructor
@RestController
public class ApiController {

    @GetMapping("/LoggingTest")
    public String Logging(){
        return "Logging Test Success";
    }

}

5. 결과 확인

LoggingTest에 접속하게 되면 요청과 응답 로그가 출력되는 것을 확인할 수 있습니다.

 

궁금한 사항 또는 잘못된 사항이 있으면 댓글 남겨주세요!

출처 : https://www.baeldung.com/spring-aop

 

Introduction to Spring AOP | Baeldung

Discover the core Spring AOP along with its basic terminology.

www.baeldung.com

,https://shinsunyoung.tistory.com/67

'Spring' 카테고리의 다른 글

Autowire 알아보기 - 2  (0) 2020.09.27
Autowire 알아보기 - 1  (0) 2020.09.27
Spring Web Layer 알아보기  (0) 2020.07.12
SpringBoot - ExceptionHandler  (1) 2020.07.05
[토이 프로젝트] IT Article - 1  (0) 2020.06.28