Spring&Spring Boot

(Spring Controller Logging) Spring에서 http request 로깅하기 - 1

Developer RyanKim 2020. 1. 6. 11:29

Spring Controller Logging - Spring에서 http request 로깅하기

   @GetMapping("/{code}")
    public ResponseEntity<ApiResponse> example(
            @PathVariable(name = "code") String code {
        final String requestUri = request.getRequestURI();
        
        log.info(LogHelper
                .getMessageWithPrefix("Request URI : " + requestUri + " | code : " + code));
...

 

요청을 처리할 때 호출되는 Controller Method의 최상단 부분 코드입니다.

log.info(LogHelper.getMessageWithPrefix("Request URI : " + requestUri + " | code : " + code));

 

한눈에 봐도 의도가 보이지 않나요? 어떤 URI를 통해 요청을 하였는지와 파라메터까지 Logging 하는 것입니다.

하지만 Method에 중복으로 이런 코드가 있다면 여러 문제가 있을 것입니다.

문제점 -
1. 핵심 기능을 파악하기 어지럽게 만듭니다.
2. 관리가 되지 않습니다. ( Logging 포맷이 변경되거나 사용 라이브러리가 변경 될 경우 일일히 다 바꾸어 주어야함)
3. 개발자가 실수할 수 있습니다. ( 해당 부분을 빼먹거나, 필요한 파라메터를 로깅에 포함 하지 않는일이 발생할 수 있음)
4. 무엇보다 더럽습니다! (엄청난 중복코드로 인해 코드 라인 수가 쓸데없이 길어짐)

따라서  Controller의 Method에 코드를 추가하여 Logging 하지 않고 요청을 처리하기전에 해당 요청을 Logging 할 수 있도록 하면 어떨까요?
먼저 아래처럼 조건과 결과를 간단하게 정리해 보았습니다.


목적
1.
현재 Controller method 안의 request 로깅을 위한 중복코드를 제거

2. 일관된 Logging 포맷

조건

1. 기존 모든 Controller method request 로깅 관련 코드를 대체할 있어야한다.

2. 필요한 모든 정보를 로그에 담을 있어야 한다.

3. 기존 비즈니스 로직에 영향이 없어야 한다.

 

고려사항

1. Controller dispatch 로깅 설정 ( Filter / Interceptor )

- ServeltDispatcher 전에 로깅을 하는 것이 좋다고 판단하여 Filter 선택

2. AOP 활용하여 Controller Class logging 동작 주입

결론

고려사항의 1번의 경우 request 자체만 로깅이 되고 어떤 메소드가 실행되는지는 로깅이 불가함.
모든 Client request 로깅하는 (고려 1) Controller Method 로깅하는 (고려 2) 성격이 아예 다른 것으로 생각하였고, 기존 로깅 코드는 2번으로 대체하는 것이 좋다고 판단

 

* 추후 filter 단에서 로깅 필요시 추가 개발필요


 

이해를 돕기 위해 위 그림에서 보면, 1번 (request dispatch 전), 2번 (controller method 시작전) 중에
2번을 택한 것 입니다.

그럼 모든 Controller Method 시작 전에 특정 기능을 수행하려면 어떻게 구현해야 할까요?

바로 AOP를 활용하면 좋겠다는 생각이 들었습니다.

/**
 * Developer : ryan kim
 * Date : 2019-10-14
 */

@Aspect
@Order(Ordered.HIGHEST_PRECEDENCE)
@Component
@Slf4j
public class LoggingAspect {

    // RestController,Controller public Method
    @Around("(within(@org.springframework.stereotype.Controller *)"
            + "|| within(@org.springframework.web.bind.annotation.RestController *))"
            + "&& execution(public * *(..))")
...


다음 포스트에서 AOP를 활용하여 어떻게 Controller Method Logging을 구현할수 있는지 자세하게 다루어 보겠습니다!

다음포스트 ↓
https://lion-king.tistory.com/entry/Spring-http-request-logging-with-aop-2

 

(Spring Controller Logging) Spring에서 http request 로깅하기 - 2

https://lion-king.tistory.com/entry/Spring-http-request-logging-with-aop-1 (Spring Controller Logging) Spring에서 http request 로깅하기 - 1 Spring Controller Logging - Spring에서 http request 로..

lion-king.tistory.com

By Ryankim