API에 대한 로깅 누구를 사용할까?(Interceptor vs Filter vs AOP)

한잔해·2025년 4월 22일

과제를 하는 도중 Interceptor와 AOP를 활용한 API 로깅 관련해서 조건으로 "어드민 사용자만 접근할 수 있는 특정 API에는 접근할 때마다 접근 로그를 기록해야 합니다." 라는 문구가 있었다. 바로 보고 방법이 떠오르지가 않는다. 모르니까..
API 로깅 관련해서 중요성은 알고있었지 실제로 구현해본적이 없어 확실하게 개념을 잡는 마인드로 가보자고

ℹ️ API 로깅은 API에 어떻게 사용되고 있는지 추적하고 기록하는 과정,
간단하게 말하면 API를 누가, 언제, 어떻게 사용했는 지에 대한 정보를 수집하고 저장하는 것


✨ 인터셉터(Interceptor)

💡 인터셉터Spring Framework에서 제공하는 기능으로, DispatcherServlet컨트롤러를 호출하기 전/후, 그리고 를 렌더링하기 전/후에 특정 로직을 수행할 수 있도록 해준다. 주로 인증, 로깅, 권한 검사 등에 사용된다.


순수 자바만 사용한다면 직접 인터셉터라는 인터페이스를 만들어서 사용할 수도 있지만, 스프링에서는 '스프링 인터셉터'라는 것을 미리 만들어두고 사용하고 있다.
따라서 스프링에서는 HandlerInterceptor라는 인터페이스를 미리 만들어 두어서 이걸 구현해서 인터셉터를 쉽게 생성할 수 있다.

동작 방식

  • preHandle() : 컨트롤러 호출 전에 실행. 요청을 가로체어 사전 처리 작업을 수행한다.
  • postHandle() : 컨트롤러가 요청을 처리한 후, 를 렌더링하기 전에 실행된다. 컨트롤러의 응답 결과를 변경하거나 추가 작업을 수행할 수 있다.
  • afterCompletion() : 렌더링까지 완료된 후 실행된다. 예외 처리, 리소스 정리 드의 작업을 수행.

장점

  • Spring Framework에 종속적이므로 Spring 환경에서 사용하기 편리하다.
  • 컨트롤러에 접근하기 전/후에 세밀한 제어가 가능하다.
  • 요청과 응답에 대한 전반적인 로깅을 구현하기에 적합하다.

단점

  • Spring Framework에 종속적이다.
  • Servlet API에 직접 접근하기 어렵다.
  • 예외 발생 시 처리 로직이 복잡해질 수 있다.

구현 예시

public class LoggingInterceptor implements HandlerInterceptor {
	@Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    	// 로깅 로직 (요청 정보 기록)
    }
    
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModleAndView modelAndView) throws Exception {
    // 로깅 로직 (응답 정보 기록)
	}
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    // 로깅 로직
	}
}

✨ 필터(Filter)

💡 필터는 Servlet API에서 제공하는 기능으로, 클라이언트의 요청이 DispatcherServlet에 도달하기 전/후에 특정 작업을 수행한다. 주로 요청/응답 데이터 변환, 인증/인가, 로깅 등에 사용


클라이언트가 요청을 보내면 서블릿 컨테이너에 위치한 필터가 요청과 응답을 가로채서 어떠한 작업을 진행 할 수 있다.

동작 방식

  • init(): 필터 초기화 메서드로, 필터가 생성될 때 한 번 호출됩니다.
  • doFilter() : 요청과 응답을 가로채어 필터링 작업을 수행. 필터 체인을 통해 여러 필터를 순차적으로 거치게 된다.
  • destroy(): 필터가 제거될 때 호출되어 자원을 해제합니다.

장점

  • Servlet API 표준이므로 Spring Framework에 독립적으로 사용 가능하다.
  • 요청과 응답 객체에 직접 접근하여 조작 가능하다.
  • 웹 애플리케이션 전반에 걸쳐 적용되는 로깅을 구현하기에 적합하다.

단점

  • Spring Context 외부에서 동작하므로 Spring Bean에 접근하기 어렵다.
  • 인터셉터에 비해 세밀한 제어가 어렵다.

구현 예시

public class LoggingFilter implements Filter {
	@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOExeption, ServletException {
    	// 로깅 로직 (요청 정보 기록)
        chain.doFilter(request, response); // 다음 필터로 진행
        // 로깅 로직 (응답 정보 기록)
    }
}

✨ AOP(Aspect-Oriented Programming)

💡 AOP는 관점 지향 프로그래밍으로, "공통적으로 들어가는 관심사"를 효율적으로 관리하고 재사용하기 위한 프로그래밍 패러다임. 로깅, 보안, 트랙젹션 관리 등에 사용된다.

위에 2가지 서비스에서 비즈니스 로직을 제외한 나머지가 공통적으로 들어간다.(트랜젹선, 로깅..)
따라서 부가적으로 수행되는 공통적인 로직을 묶어서 앞단에서 관리하고 수행하도록 만드는 방법

동작 방식

  • Advice : Aspect가 언제, 어디에 적용될지를 정의 (ex : 메서드 실행 전/후)
  • target : Advice가 적용될 객체
  • Join Point : Advice가 적용될 수 있는 지점, Spring AOP에서는 메서드가 실행될 때만 적용되도록 한정하고 있다. (ex : 메서드 실행 시점)
  • Pointcut : Advice를 적용할 Join Point를 지정, advice가 적용될 수 있지만 적용되지 않는 곳도 존재, point cut은 join point 중에서도 advice가 적용되는 지점 (ex : 특정 메서드 패턴)
  • Aspect : 횡단 관심사를 모듈화한 코드, 이는 advice와 pointcut을 합친 것으로, 무엇을 언제 어디서 할지에 대한 정보가 모두 정의 되어있다.

    횡단 관심사 : 여러 핵심 관심사에 걸쳐서 공통적으로 필요한 기능, ex. "사용자 인증". "상품 주문" 등은 모든 핵심 관심사에서 필요할 수 있다.

장점

  • 핵심 비지니스 로직과 부가 기능을 분리하여 코드의 재사용성을 높이고 유지보수를 용이하게 한다.
  • 관심사를 모듈화하여 코드의 응집도를 높인다.
  • 기존 코드를 수정하지 않고 기능을 추가할 수 있다.

단점

  • AOP 개념에 대한 이해가 필요하며, 복잡도가 증가할 수 있다.
  • 잘못된 AOP 적용은 성능 저하를 야기할 수 있다.

구현 예시

어노테이션설명
@Before비지니스 로직 실행 전
@AfterReturning비지니스 로직 실행 결과가 정상적으로 반환된 후
@AfterThrowing비지니스 로직 실행 시 예외가 발생된 후
@After비지니스 로직 실행 후
@Around비지니스 로직 실행 전과 후
@Aspect
@Component
public class LoggingAspect {
	@Before("execution(* com.example.api. *Controller.*(..))")
    public void before(JoinPoint joinpoint) {
    	// 로깅 로직 (메서드 실행전)
    }
    
    @AfterReturning(pointout = "execution(* com.example.api. *Controller.*(..))", returning = "result")
    public void afterReturning(JoinPoint joinPoint, Object result) {
    	// 로깅 로직 (메서드 실행 후, 반환값 기록)
    }
}

📚 로깅 사용 시 선택 가이드

선택역할추가 설명
필터모든 요청에 대한 초기 단계 로깅 및 Spring 외부 요소 제어.Spring MVC에 들어오기 전 단계에서 처리하므로, 요청/응답 전체를 로깅하거나 CORS, 보안 관련 로깅에 적합.
인터셉터특정 API에 대한 MVC 흐름 내 로깅 및 전/후 처리.컨트롤러 호출 전/후에 필요한 로깅, 권한 검사, 데이터 변환 등에 유용.
AOP세밀한 제어가 필요한 특정 API 로깅 및 예외 상황 관리.메서드, 파라미터, 반환값 등 상세 정보를 기록하고, 예외 발생 시 로깅을 포함하는 복잡한 로깅 요구사항에 적합.
  • 선택 팁

    • 전체적인 요청/응답 로깅: 필터
    • 특정 API의 일반적인 로깅 및 전/후 처리: 인터셉터
    • 특정 API의 상세한 로깅 및 예외 처리, 유연한 설정: AOP
  • 예시

    • 모든 요청의 IP 주소, 요청 시간 로깅: 필터
    • 특정 API 호출 시 사용자 권한 검사 및 로깅: 인터셉터
    • 특정 API의 파라미터, 실행 시간, 반환 값, 예외 발생 시 스택 트레이스 로깅: AOP

참고 블로그
https://qkrqkrrlrl.tistory.com/175#%EC%9D%B8%ED%84%B0%EC%85%89%ED%84%B0-1
https://velog.io/@youjung/Spring-AOP
https://velog.io/@whale004/Spring6%EA%B8%B0-Spring-%EC%8B%AC%ED%99%94-%EC%A3%BC%EC%B0%A8-%EA%B0%9C%EC%9D%B8-%EA%B3%BC%EC%A0%9C

profile
항상 배우고 탐구하는 노력하는 개발자

0개의 댓글