Interceptor 하다 :
는 가로채다 라는 의미의 영단어 입니다! 한마디로 무언가를 중간에 가로채는것을 인터셉터!
라고 한다는거죠??? 그렇다면 무엇을 가로채는걸까요??
바로 Client 의 요청으로 서버에 들어온 request 객체를 가로채는것 입니다.
Controller에서 Handler 로 도달하기전에 그 순간 요청을 가로챕니다.
여기서 말하는 Handler란? ⇒ 사용자가 요청한 url주소에 따라 실행될 메소드를 의미합니다!
그러면 굳이 왜 요청을 가로채냐고요?? 당연히 Handler로 도달하기전에 추가로 작업해야될 것들을
실행 시킨뒤에 Handler로 가게 만드는 것이죠! Interceptor 는 단순히 하나의 요청만을 가로채는게 아닌
여러개의 요청을 동일한걸로 엮어서 한번에 똑같은 작업을 명령할 수 있어서
Module이라고 부릅니다!
흐름:
**DispatcherServlet**은 HandlerMapping에게 Client Request를 수행 할 Handler를 찾도록 요청을 보냅니다.
이때 HandlerExecutionChain(핸들러 실행 체인)이 동작하는데,
**HandlerExecutionChain**은 하나 이상의 HandlerInterceptor를 거쳐 Controller가 실행되도록 구성되어 있습니다.
HandlerInterceptor를 등록하지 않았을 경우 바로 Controller 실행을 하게 되고, 등록을 했다면
HandlerInterceptor를 거쳐 Request에 대해 원하는 작업, 로직을 수행한 후 Controller로 Request 객체를 전달합니다.
이 쯤 되면 당연히 눈치 채셨겠지만, 인터셉터의 제일 큰 장점들을
- 코드의 중복성 제거
- 메모리 낭비 및 서버 과부화 감소
- 코드가 많아질시 누락으로 인한 에러확률 감소
입니다. 예를 들어 해당 웹페이지에 클라이언트가 요청을 보내게 됬을때, 아이디 세션값의 유효성을 확인해야하는 페이지가 1000개라면,
1000개 의 컨트롤러 메소드에 모두 코드를 작성해줘야 하지만, 인터셉터를 활용하면 코드 하나 작성하고 적용해야할 메소드명만 명시해주면,
해당 요청을 받게 됬을때 모두 인터셉터가 먼저 요청을 처리하고 해당 url로 보내주게 됩니다.
즉 수많은 코드의 중복성이 제거 되고, 재이용성이 많아지며 혹시라도 실수로 코드 누락이 생겨 안전성에 결함이 발생되는걸 막아줍니다!
예제:
일단 코드를 봐야지 좀 더 느껴질꺼 같네요!
그래서 간단하게 예제코드를 작성하여 보여드리겠습니다!
기본설정
Interceptor를 쓰기 위해서는 제일 먼저 준비해야 될게 몇가지 있습니다.
1. Interceptor Class 생성
인터셉터 발생시 생성한 인터셉터 구현 클래스로 오게 되는데, 인터셉터 클래스 구현시 따라야 하는 규칙이 있습니다.
Spring에서 Interceptor의 구현은 HandlerInterceptor(Interface)나 HandlerInterceptorAdapter(Abstract Class)로 구현할 수 있습니다.
HandlerInterceptorAdapter Abstract Class는 HandlerInterceptor Interface를 상속받아 구현됩니다.
위 두가지 중 하나를 구현하는 Class를 생성한 후,
DispatcherServlet의 Context(servlet-context.xml || 직접 작성한 context.xml)에 작성 Interceptor Class를 Bean 등록하고,
적용 Url을 명시해주면 된다.
// HandlerInterceptor 상속
public class Interceptor implements HandlerInterceptor
{
}
// HandlerInterceptorAdaptor 상속
public class Interceptor extends HandlerInterceptorAdapter
{
}
2. DistpatcherServlet의 Context 파일(servlet-context.xml)에 Interceptor Class와 적용 URL을 명시한다.
Interceptor에서 제외하고 싶은 경로가 있을경우 <mvc:exclude-mapping path=""/>를 활용한다.
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/account/logout"/>
<bean class="com.public.app.Interceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
3. 설정한 Interceptor 클래스에서 DistpatcherServlet 에서 핸들러로 요청을 처리하기전
실행한 로직들을 구현하고 실행한다.
ublic class LoginInterceptor extends HandlerInterceptorAdapter {
//컨트롤러 실행전 호출되는 메소드
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{
// 로그인 여부를 확인하여 로그인 세션이 있으면 => pass
// 로그인 세션이 없으면 로그인 페이지로 이동
HttpSession session = request.getSession();
String useridid = (String)session.getAttribute("userid");
if(userid==null || userid.equals("")) {
response.sendRedirect(request.getContextPath()+"/member/login");
return false; // 부정은 로그인 홈페이지로 돌아가 이쉐꺄!!! 이런거임;;
}
return true;
}
//컨트롤러 실행후 View 페이지로 이동하기전에 호출되는 메소드
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception{
}
//컨트롤러 실행후 호출되는 메소드
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception{
}
}
당연히 상속받은 HandlerInterceptorAdapter의 메소드를 오버라이드 해서 사용하는거기 때문에 틀은 정해졌있다.
하지만 그것을 가지고 어떤 내용을 실행시킬지는 위와 같은 코드처럼 작성하면 되는것이다.
이때 메소드의 반환형타입이 boolean인데 true이면 핸들러로 요청을 넘기는 것이고, false이면 클라이언트의 요청을 인터셉터가 가로채셔
다른 곳으로 보내는것이다.
즉 ⇒ true는 핸들러로 이동 false는 인터셉터가 요청을 처리한다.
주로 많이 쓰이는 경우는, 로그인이 되어있지 않을때 로그인 홈페이지로 보내는 기능을 합니다!
그래서 로그인이 필요한 페이지로 이동시에는 미리 인터셉터를 설계해, 바로 로그인 홈페이지로 이동하게 만드는것이죠!
'Spring & Spring Boot' 카테고리의 다른 글
Spring bean(빈이란?) (0) | 2023.01.16 |
---|---|
IOC (Inversion Of Control) 제어의 역전 .feat “Container” (0) | 2023.01.16 |
Spring Framework 파일업로드 하기 (2) | 2023.01.16 |
DI (Dependency Injection) 의존성 주입 (0) | 2023.01.16 |
MVC 패턴?…What the….?? (0) | 2023.01.16 |