1. 인터셉터 - HandlerInterceptor 인터페이스


Interceptor는 Spring에서 제공하는 기능 중 하나입니다. (Spring Framework를 사용하지 않는다면 Filter로 대체할 수 있습니다.) 클라이언트가 URL 요청을 보내면 해당 URL 매핑을 가지는 Controller에서 해당 메서드를 실행시킬텐데,

이때, 요청 흐름 사이사이에 로직을 끼워넣을 수 있습니다.

보통 3가지 흐름에 로직을 끼워넣습니다.

  1. Controller의 요청 메서드를 실행시키기 전
  2. Controller의 요청 메서드를 실행시킨 후
  3. View 처리가 끝난 후

Interceptor는 HandlerInterceptor 인터페이스를 구현하여 만들 수 있습니다.

그중, 자주 사용되는 구현체는 HandlerInterceptorAdaptor 클래스입니다.

Interceptor가 요청의 어느 흐름에 관여하는지 그림으로 나타내보겠습니다.

[그림 1] 요청흐름에서 Interceptor의 위치

HandlerInterceptor 인터페이스의 3가지 메서드만 나타냈습니다.(더 있지만 주로 이 3개를 사용합니다.)

  1. preHandler() 메서드 : 컨트롤러의 요청 메서드가 실행되기 전에 실행.
  2. postHandler() 메서드 : 컨트롤러의 요청 메서드가 실행된 후에 실행.
  3. afterCompletion() 메서드 : 뷰 처리가 끝난 직후에 실행.

다른건 몰라도 preHandler() 메서드로 뭘 해야할지는 딱 떠오르지 않나요🤔? 바로 로그인했는지 체크여부입니다.

주로 Interceptor로 로그인, 권한 체크를 합니다.

2. preHandler() 메서드를 이용해 로그인 인터셉터 구현하기


Interceptor를 사용하지 않고 로그인 여부를 확인해줄려면 어떻게 해야할까요?

모든 요청 URL에 해당하는 Controller마다 로그인 체크 로직을 추가줘야할 것입니다. 

로그인이 되었는지 체크하는 로그인 인터셉터는 다음과 같이 구현할 수 있습니다.

public class LoginInterceptor extends HandlerInterceptorAdapter {
    @Override
    public boolean preHandle(HttpServletRequest req, HttpServletResponse res, Object handler) throws Exception {
        HttpSession httpSession = req.getSession(false);
        if (httpSession != null) {
            Object obj = httpSession.getAttribute("user"); // 세션에 있는 user 속성값을 가져온다.
            if (obj != null) return true; // 세션에 user 속성값이 있다면 true를 리턴해 컨트롤러의 로직을 정상 실행.
        }
        // 여기까지 내려왔다면 세션에 user 속성값이 없다는 뜻이므로 로그인 화면으로 리다이렉트 !
        res.sendRedirect(req.getContextPath() + "/login");
        return false;
    }
    @Override
    public void postHandle(HttpServletRequest req, HttpServletResponse res, Object handler, ModelAndView mav) throws Exception {
        super.postHandler(req, res, handler, mav);
    }
    @Override
    public void afterCompletion(HttpServletRequest req, HttpServletResponse res, Object handler, Exception e) throws Exception {
        super.afterCompletion(req, res, handler, e);
    }
}

이제 위의 로그인 인터셉터를 적용시키기 위해 2가지를 해야합니다.

  1. LoginInterceptor 클래스를 빈으로 등록합니다.
  2. <mvc:interceptor> 태그를 이용해 인터셉터를 적용할 경로를 매핑합니다.
<bean id="loginInterceptor" class="com.pangtrue.commons.interceptor.LoginInterceptor"/>

<mvc:interceptors>
    <mvc:interceptor>
       <mvc:mapping path="/*"/>
       <ref bean="loginInterceptor">
    </mvc:interceptor>
</mvc:interceptors>