Interceptor 란 Filter와 매우 유사한 형태로 존재 하지만, 차이점은 Spring Context에 등록 된다. AOP와 유사한 기능을 제공 할 수 있으면, 주로 인증 단계 를 처리하거나, Logging 를 하는데 사용한다. 이를 선/후 처리 함으로써, business logic과 분리 시킨다.

Spring Boot에서 인터셉터(Interceptor)는 요청을 처리하기 전과 후에 실행되는 코드로,
**컨트롤러(Controller)에 도달하기 전과 후에 사용자 지정 작업을 수행할 수 있습니다**.
인터셉터는 로깅, 인증, 인가, 데이터 변환 등의 공통 작업을 수행하는 데 사용됩니다.

인터셉터를 구현하려면
**`org.springframework.web.servlet.HandlerInterceptor`** 
인터페이스를 구현하는 클래스를 작성해야 합니다. 이 인터페이스에는 세 가지 메서드가 있습니다

1. **`preHandle()`**: 컨트롤러가 실행되기 전에 호출되는 메서드입니다. 
이 메서드는 요청을 가로채서 필요한 작업을 수행한 후, 
요청 처리가 계속되어야 하는지 여부를 결정합니다. 
반환 값이 **`true`**이면 요청 처리가 계속되며, **`false`**인 경우 요청 처리가 중단됩니다.

2. **`postHandle()`**: 컨트롤러 실행 후 호출되지만, 
뷰(View)가 렌더링되기 전에 호출되는 메서드입니다. 
이 메서드는 컨트롤러가 요청을 처리한 후에 필요한 후 처리 작업을 수행하는 데 사용됩니다.

3. **`afterCompletion()`**: 요청 처리가 완료된 후, 
즉 뷰 렌더링이 완료된 후에 호출되는 메서드입니다. 
이 메서드는 자원을 정리하거나 추가 로깅 등의 작업을 수행하는 데 사용됩니다.

인터셉터를 구현한 후에는 **`WebMvcConfigurer`** 인터페이스를 구현하는 구성 클래스를 작성하여 
인터셉터를 등록해야 합니다. 이 구성 클래스에서 **`addInterceptors()`** 메서드를 
오버라이드하여 인터셉터 인스턴스를 등록할 수 있습니다.

예를 들어 다음과 같이 인터셉터를 등록할 수 있습니다

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new CustomInterceptor());
    }
}

이렇게 하면 인터셉터가 Spring Boot 애플리케이션에서 활성화되어 요청 처리 전,
후에 실행됩니다. 필요에 따라 인터셉터를 여러 개 등록하거나, 
특정 경로 또는 패턴에만 적용할 수도 있습니다.
인터셉터 구현 순서 

1. HandlerInterceptor 를 구현한 클래스를 직접 정의 한다. 
2. WebMvcConfigurer 인터페이스를 구현한 클래스를 정의하고 1 번에서 만든 클래스를 
등록 해주어야 한다.

예시 코드 : 컨트롤러 만들어 주기

package com.example.demo10.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class UserController {
		
	@GetMapping("/loginPage")
	public String loginPage() {
		return "login.html";  // 내부에서 이동 
	}
	
	/**
	 * 인증된 사용자만 들어 올 수 있게 막을 예정
	 * AuthInterceptory 동작 시킬려면 주소 설계를 /auth/** 
	 */
	@GetMapping("/auth/infoPage") 
	public String infoPage(HttpServletRequest request) {
		// 테스트
		// todo  
		// 1. 아래 부분 삭제 예정
		// 2. 인터셉터가 동작 하도록 주소 변경 예정
		
//		HttpSession session = request.getSession();
//		Object principal = session.getAttribute("principal");
//		if(principal == null) {
//			return "redirect:/loginPage";
//		}
		
		System.out.println("여기 코드 실행 할려면 로그인 되야 함");
		// 상대 위치 들었음 -- 현재 그 시점에서 맞게 설계 
		// 위치에서 상대 경로 찾을지 절대 경로 찾을지 결정 
		return "/info.html";
	}
	
}

인터셉터 만들어 주기

package com.example.demo10.handler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

// AuthInterceptor 는 request 요청이  
// 앞에 /auth/** 로 요청한 주소에서만 동작 하도록 설계 할 예정
@Component // IoC 처리 확인 
public class AuthInterceptor implements HandlerInterceptor {
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
	
		// 세션 여부 확인 
		HttpSession session = request.getSession();
		Object principal = session.getAttribute("principal");
		
		if(principal == null) {
			System.out.println("인증 안된 사용자");
			response.sendRedirect("/loginPage");
			return false; 
		}
		
		return true;
	}
	
}

인터셉터 등록하기

package com.example.demo10.handler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

	@Autowired // DI 적용 
	private AuthInterceptor authInterceptor;
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		
		// 규칙 
		// 주소요청이 /auth/** 이 붙으면 AuthInterceptor 동작 
		// 하도록 구현 처리 
		registry.addInterceptor(authInterceptor)
				.addPathPatterns("/auth/**");
		
	}
}

시나리오 코드 1

package com.example.demo8.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController // IoC 대상
public class PublicController {
	
	// http:localhost:8080/hello
	@GetMapping("/hello")
	public String hello() {
		System.out.println("Controller 에서 메서드 실행");
		return "hello";
	}
}
package com.example.demo8.handler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

/**
 * 
 * 인터셉터 만들기 
 * 1. HandlerInterceptor 구현 처리
 * 2. 3 가지 메서드 기억  
 */
// 어노테이션 사용하지 않았음 !!! 
public class LoggingInterceptor implements HandlerInterceptor {
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		
		System.out.println("----------------");
		System.out.println("Request URI : " + request.getRequestURI());
		System.out.println("Request Method : " + request.getMethod());
		
		return true; 
	}
	
	
	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
	}
	
	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
	}
	
}
package com.example.demo8.handler;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 
 * @author 
 * 1. WebMvcConfigurer 구현 처리 하기 
 * 2. addInterceptors 를 구현 해야 한다. 
 */
@Configuration // 1개 이상 빈으로 등록 해야 할 때 
public class WebMvcConfig implements WebMvcConfigurer {
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		// 우리가 직접 만든 인터셉터 구현클래스를 등록 처리 합니다.
		registry.addInterceptor(new LoggingInterceptor());
	}
}

코드를 DI 사용하는 걸로 변경해 보자.

package com.example.demo8.handler;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * 
 * @author 
 * 1. WebMvcConfigurer 구현 처리 하기 
 * 2. addInterceptors 를 구현 해야 한다. 
 */
@Configuration // 1개 이상 빈으로 등록 해야 할 때 
public class WebMvcConfig implements WebMvcConfigurer {
	
	// DI를 사용하는 코드로 변경해 보자.
	@Autowired  // DI 적용 
	private LoggingInterceptor loggingInterceptor;
	
//	public WebMvcConfig(LoggingInterceptor loggingInterceptor) {
//		this.loggingInterceptor = loggingInterceptor;
//	}
	
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
		// 우리가 직접 만든 인터셉터 구현클래스를 등록 처리 합니다.
		registry.addInterceptor(loggingInterceptor);
	}
}

'Spring boot' 카테고리의 다른 글

Spring boot - Interceptor - 2(활용)  (1) 2023.04.17
스프링 부트 JSP 연결  (0) 2023.04.13
spring boot execption(예외처리)  (0) 2023.04.13
Spring Boot Validation  (0) 2023.04.13
어노테이션 종류  (0) 2023.04.13

+ Recent posts