본문 바로가기

Backend/Spring

Spring Boot Interceptor 적용

스프링에서 공통적으로 처리할 로직을 구현하고 싶을 때가 있어요.

대표적으로 Java Filter, Spring Interceptor, Spring AOP를 활용할 수 있는데요.

 

이 글에선 Interceptor를 활용하여 특정 URI들의 요청을 가로채서 역할을 수행할 수 있도록 구현해볼거에요.

Interceptor는 Spring Container 영역이며 Servlet 단위에서 실행되요.

인증/권한 처리, 로직 시간 계산, 로깅 등을 공통적으로 처리하고 싶을 때 사용해요.

AuthInterceptor

이름만 Auth로 써봤어요. 실제로는 로그만 찍을겁니다.

AuthInterceptor 클래스에 HandlerInterceptor 인터페이스를 구현할거에요.

스프링에서 다해줘요. 우리는 비즈니스 로직만 구현하면 되요.

특정 Request를 호출할 때마다 AuthInterceptor에서 구현한 메서드가 동작해요.

  • preHandle : @Controller 호출 이전에 동작
  • postHandle : @Controller 호출 이후에 동작
  • afterCompletion : 화면 처리까지 모두 끝나면 동작

정확하게는 @Controller가 아니라 HandlerAdapter가 핸들러를 호출하는 시점이지만, 이해하기 쉽도록 지금은 @Controller 정도로 알고 계셔도 될 것 같아요.

궁금하신 분은 Spring Framework HandlerAdapter에 대해서 찾아보시면 어렵지 않게 이해할 수 있을 거에요.

 

@Slf4j
@Component
public class AuthInterceptor implements HandlerInterceptor {

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		log.info("preHandle!!");
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		log.info("postHandle!!");
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		log.info("afterCompletion!!");
	}

}

 

WebMvcConfig

구현한 인터셉터를 사용할 수 있도록 설정할거에요.

/user/로 시작하는 패턴은 가로채지 못하도록 제외하였어요.

 

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

	@Autowired
	private AuthInterceptor authInterceptor;

	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		registry.addInterceptor(authInterceptor)
		.addPathPatterns("/event/**")
		.excludePathPatterns("/user/**");
	}

}

EventController

@Slf4j
@RestController
@RequestMapping("event")
public class EventController {
	
	@Autowired
	private EventsRepo eventsRepo;
	
	@GetMapping("")
	public Page<EventsDoc> getList(Pageable pageable) {
		log.info("Event!!");
		return eventsRepo.findAll(pageable);
	}

}

 

테스트해볼게요.

http://localhost:8080/event

 

 

http://localhost:8080/user

호출하면 인터셉트의 로직을 수행하지 않음을 확인할 수 있어요.

 

아래와 같은 부분들 잘 판단해서 적용하시면 좋을 것 같아요.

  • REST 아키텍처에서는 Interceptor 도입하기 전에 고려해야할 사항이 있어요. Interceptor는 URI 패턴을 체크하여 요청을 가로채는데 REST는 URI 패턴이 같으면서 Method가 다른 요청들이 많기 때문이죠.
  • URI 패턴에 공통적인 부분이 별로 없을 때 Interceptor를 사용하면 불리해요. 이런 경우에는 일반적으로 설계하듯이 로직을 객체화한 후 수행할 컨트롤러의 메서드에 일일이 추가해주는 것이 수월할 수도 있어요.