과제를 하는 도중 Interceptor와 AOP를 활용한 API 로깅 관련해서 조건으로 "어드민 사용자만 접근할 수 있는 특정 API에는 접근할 때마다 접근 로그를 기록해야 합니다." 라는 문구가 있었다. 바로 보고 방법이 떠오르지가 않는다. 모르니까..
API 로깅 관련해서 중요성은 알고있었지 실제로 구현해본적이 없어 확실하게 개념을 잡는 마인드로 가보자고
ℹ️ API 로깅은 API에 어떻게 사용되고 있는지 추적하고 기록하는 과정,
간단하게 말하면 API를 누가, 언제, 어떻게 사용했는 지에 대한 정보를 수집하고 저장하는 것
💡 인터셉터는
Spring Framework에서 제공하는 기능으로,DispatcherServlet이컨트롤러를 호출하기 전/후, 그리고뷰를 렌더링하기 전/후에 특정 로직을 수행할 수 있도록 해준다. 주로 인증, 로깅, 권한 검사 등에 사용된다.
순수 자바만 사용한다면 직접 인터셉터라는 인터페이스를 만들어서 사용할 수도 있지만, 스프링에서는 '스프링 인터셉터'라는 것을 미리 만들어두고 사용하고 있다.
따라서 스프링에서는 HandlerInterceptor라는 인터페이스를 미리 만들어 두어서 이걸 구현해서 인터셉터를 쉽게 생성할 수 있다.
preHandle() : 컨트롤러 호출 전에 실행. 요청을 가로체어 사전 처리 작업을 수행한다.postHandle() : 컨트롤러가 요청을 처리한 후, 뷰를 렌더링하기 전에 실행된다. 컨트롤러의 응답 결과를 변경하거나 추가 작업을 수행할 수 있다.afterCompletion() : 뷰 렌더링까지 완료된 후 실행된다. 예외 처리, 리소스 정리 드의 작업을 수행.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 {
// 로깅 로직
}
}
💡 필터는 Servlet API에서 제공하는 기능으로, 클라이언트의 요청이 DispatcherServlet에 도달하기 전/후에 특정 작업을 수행한다. 주로 요청/응답 데이터 변환, 인증/인가, 로깅 등에 사용
클라이언트가 요청을 보내면 서블릿 컨테이너에 위치한 필터가 요청과 응답을 가로채서 어떠한 작업을 진행 할 수 있다.
init(): 필터 초기화 메서드로, 필터가 생성될 때 한 번 호출됩니다.doFilter() : 요청과 응답을 가로채어 필터링 작업을 수행. 필터 체인을 통해 여러 필터를 순차적으로 거치게 된다.destroy(): 필터가 제거될 때 호출되어 자원을 해제합니다.public class LoggingFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOExeption, ServletException {
// 로깅 로직 (요청 정보 기록)
chain.doFilter(request, response); // 다음 필터로 진행
// 로깅 로직 (응답 정보 기록)
}
}
💡 AOP는 관점 지향 프로그래밍으로, "공통적으로 들어가는 관심사"를 효율적으로 관리하고 재사용하기 위한 프로그래밍 패러다임. 로깅, 보안, 트랙젹션 관리 등에 사용된다.
위에 2가지 서비스에서 비즈니스 로직을 제외한 나머지가 공통적으로 들어간다.(트랜젹선, 로깅..)
따라서 부가적으로 수행되는 공통적인 로직을 묶어서 앞단에서 관리하고 수행하도록 만드는 방법
횡단 관심사 : 여러 핵심 관심사에 걸쳐서 공통적으로 필요한 기능, ex. "사용자 인증". "상품 주문" 등은 모든 핵심 관심사에서 필요할 수 있다.
| 어노테이션 | 설명 |
|---|---|
| @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 로깅 및 예외 상황 관리. | 메서드, 파라미터, 반환값 등 상세 정보를 기록하고, 예외 발생 시 로깅을 포함하는 복잡한 로깅 요구사항에 적합. |
선택 팁
예시
참고 블로그
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