본문 바로가기
컴퓨터공학/스프링

Interceptor

by 유리병 2023. 12. 5.

목차


 

Interceptor의 개념

쇼핑몰 사이트를 만들 경우, 장바구니, 찜하기, 주문 페이지에 들어가려면 반드시 로그인이 되어있어야 한다. 

 

이때 아래 코드와 같이 각 맵핑 메소드마다 session을 체크해 접속을 체크할 수도 있다.

@GetMapping("/member/regist.do")
public String regist(HttpSession sess) {
	/* 로그인 여부 체크 */
	if(sess.getAttribute("loginSess") == null) return null;
    
	return "member/write";
}

그러나 이 경우 장바구니, 찜하기, 주문 페이지 등 로그인을 요구하는 모든 페이지에서 Session을 체크하는 코드를 추가해야 한다.

 

이렇게 모든 메소드에 Session체크를 하는 부분을 다 코딩해 넣지 않고도 AOP개념을 활용해 Session을 체크하는 하나의 코드만 만든 후, 모든 요청이 들어오기 전에 먼저 Session을 체크한 후, 요청을 처리할 수 있게 하는 것이 Interceptor이다.

 

 

Interceptor 만들기

Interceptor클래스 만들기

Interceptor클래스를 만든다. 

 

Interceptor는 HandlerInterceptor인터페이스를 구현해 만든다.

HandlerInterceptor 인터페이스의 3가지 메소드

  • preHandle() : url이 컨트롤러에 도달하기 전에 수행
  • postHandle() : url이 컨트롤러에 도달한 후에 수행
  • afterCompletion() : 뷰를 실행한 후에 수행

Interface는 대개 preHandle()함수를 주로 사용한다.

preHandle()함수에서 로그인 여부를 체크해 요청을 거절하면 요청은 컨트롤러에 도달하지 않는다.

 

public class UserLoginInterceptor implements HandlerInterceptor {
	@Override
	public boolean preHandle(HttpServletRequest request, 
				HttpServletResponse response, 
				Object handler) throws Exception {
                
        	/* session에서 login여부를 확인 */
		HttpSession sess = request.getSession();
		UserVO login = (UserVO)sess.getAttribute("loginInfo");
		if (login == null) {
        		/* 로그인 정보가 없을 경우 경고를 띄우고 로그인 하는 곳으로 이동 */
			response.setContentType("text/html; charset=utf-8");
			PrintWriter out = response.getWriter();
			out.print("<script>");
			out.print("alert('로그인 후 사용가능합니다.');");
			out.print("location.href='/user/login.do';");
			out.print("</script>");
			out.close();
			return false; /* Controller로 이동 차단 */
		}
		return true;  /* 로그인 정보가 있을 경우 Controller로 이동 */
	}
}

 

 

Interceptor Bean객체 등록

Config파일에 Interceptor객체 등록

	// 인터셉터
	@Bean
	public UserLoginInterceptor userLoginIntercepton() {
		return new UserLoginInterceptor();
	}

 

Config파일에서 Interceptor 주입

@Override
public void addInterceptors(InterceptorRegistry registry) {
    	/* 빈 객체 주입 및 url 설정 */
	registry.addInterceptor(userLoginIntercepton()) // 빈 객체 주입 
       		/* user 아래로 오는 모든 요청에 대해 로그인 여부를 검사하되 */
		.addPathPatterns("/user/**")			
               	/* 아래 요청들은 로그인 여부 검사에서 제외 */
		.excludePathPatterns("/user/join.do")
		.excludePathPatterns("/user/login.do")
		.excludePathPatterns("/user/idCheck.do")
		.excludePathPatterns("/user/emailCheck.do")
		.excludePathPatterns("/user/regist.do");
}

 

 

여러개의 Interceptor Bean을 등록/설정하기

아래 코드와 같이 registry에 여러개의 interceptor를 추가해주면 된다.

// 인터셉터
@Bean
public UserLoginInterceptor userLoginIntercepton() {
	return new UserLoginInterceptor();
}
@Bean
public SellerLoginInterceptor sellerLoginIntercepton() {
	return new SellerLoginInterceptor();
}
@Bean
public CategoryInterceptor categoryInterceptor() {
	return new CategoryInterceptor();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
	// url 설정
	registry.addInterceptor(userLoginIntercepton())
		.addPathPatterns("/user/**")
		.excludePathPatterns("/user/join.do")
		.excludePathPatterns("/user/login.do")
		.excludePathPatterns("/user/idCheck.do")
		.excludePathPatterns("/user/emailCheck.do")
		.excludePathPatterns("/user/regist.do");
	
	registry.addInterceptor(sellerLoginIntercepton())
		.addPathPatterns("/seller/**")
		.excludePathPatterns("/seller/login.do")
		.excludePathPatterns("/seller/join.do")
		.excludePathPatterns("/seller/idCheck.do")
		.excludePathPatterns("/seller/emailCheck.do")
		.excludePathPatterns("/seller/regist.do");
	
	registry.addInterceptor(categoryInterceptor())
		.addPathPatterns("/")
		.addPathPatterns("/user/**")
		.addPathPatterns("/product/**");
}

 

 

Interceptor를 통해 jsp에 데이터 전달하기

public class CategoryInterceptor implements HandlerInterceptor {
	@Override
	public boolean preHandle(HttpServletRequest request, 
							HttpServletResponse response, 
							Object handler)
							throws Exception {
		
        	/* Interceptor에서 request객체를 통해 데이터를 삽입 */
		request.setAttribute("ProductCategoryVO", new ProductCategoryVO());
		return true;
	}
}

위와 같이 Interceptor를 통해 request객체에 데이터를 삽입할 경우 해당 Interceptor를 거쳐서 도달한 모든 jsp에서 해당 데이터를 사용할 수 있게된다.

 

<!-- 
    Controller에서 따로 ProductCategoryVO를 보내지 않아도
    ${ProductCategoryVO}를 사용할 수 있다
-->
<li>
<a>강아지</a>
<ul>
	<c:forEach var="category2" 
    	items="${ProductCategoryVO.category[0]}" varStatus="status">
		<li>
		<a href="/product/search.do?category1=0&category2=${status.index }">
		${category2 }
		</a>
		</li>
	</c:forEach>
</ul>
</li>

<li>
<a>고양이</a>
<ul>
	<c:forEach var="category2" 
    	items="${ProductCategoryVO.category[1]}" varStatus="status">
		<li>
		<a href="/product/search.do?category1=1&category2=${status.index }">
		${category2 }
		</a>
		</li>
	</c:forEach>
</ul>
</li>

<li>
<a>기타</a>
<ul>
	<c:forEach var="category2" 
    	items="${ProductCategoryVO.category[2]}" varStatus="status">
		<li>
		<a href="/product/search.do?category1=2&category2=${status.index }">
		${category2 }
		</a>
		</li>
	</c:forEach>
</ul>
</li>