Backend/Http+Servlet

response.sendRedirect 에 대한 오해

findmypiece 2021. 3. 16. 10:09
728x90

특정페이지로 리다이렉트 시키고 싶은 경우 response.sendRedirect() 메소드를 사용하곤 한다.

그런데 너무 예전에 생각없이 쓰던거라 이제라도 잘못된 지식을 바로 잡고자 한다.

 

나는 이 메소드를 사용할 경우 암시적으로 프로그램의 흐름이 종료되는 것으로 알고 있었다.

즉, return 과 같은 역할이 기본적으로 포함되어 있다고 착각하고 있었다.

 

결론부터 말하면 전혀 그렇지 않다.

지금까지 이렇게 착각하고 있어도 아무 문제가 없고 더 찾아보지 않았던 이유가

response.sendRedirect() 를 항상 마지막에 처리했기 때문인데

response.sendRedirect() 메소드는 response 헤더에 어느 페이지로 리다이렉트 하라는

정보를 넣는 것 뿐 실제로 프로그램의 흐름을 종료하진 않는다.

다르게 말하면 이후 정의된 코드가 있다면 이어서 수행된다는 말이다.

 

Spring 환경에서 response 객체를 사용할 수 있는 곳은

크게 Controller, Intercepter, Filter, AOP 등이 있을 수 있다.

이 중 Controller 진입이후 ModelAndView 객체를 활용할 수 있는 시점이라면

일반적으로 response.sendRedirect() 보다는 ModelAndView를 사용해서

아래와 같이 처리할 수 있고 리다이렉트 자체를 return 으로 처리하기 때문에 큰 문제가 되지 않는다.

return new ModelAndView("redirect:https://www.tistory.com");

 

하지만 ModelAndView 객체를 사용할 수 없는 시점.

즉, Controller 진입 전에 처리되는 Filter 나 Intercepter 의 preHandle 메소드에서는

response.sendRedirect() 를 사용해야 하는데

이때 적절한 return 을 해주지 않으면 우리가 원하는 리다이렉트가 정상적으로 수행되지 않을 수 있다.

 

Filter를 예로 들어보자.

public class TestFilter extends OncePerRequestFilter {

    protected void doFilterInternal(
    	HttpServletRequest request
        , HttpServletResponse response
        , FilterChain filterChain) throws ServletException, IOException {
        
        String uri = request.getRequestURI();
        if (uri.startsWith("/test/")) {
		response.sendRedirect("https://www.tistory.com");
        }

        filterChain.doFilter(request, response);
    }
    
}

 

uri가 /test/로 시작되는 경우 https://www.tistory.com 으로 리다이렉트 하려고 하지만

response.sendRedirect 이후 filterChain.doFilter 가 이어서 실행되기 때문에

정상적으로 Controller 진입이 수행될 것이고 그곳의 RequestMapping 메소드가 수행될 것이다.

이에 아래와 같이 명시적으로 return 처리를 해줘야 한다.

public class TestFilter extends OncePerRequestFilter {

    protected void doFilterInternal(
    	HttpServletRequest request
        , HttpServletResponse response
        , FilterChain filterChain) throws ServletException, IOException {
        
        String uri = request.getRequestURI();
        if (uri.startsWith("/test/")) {
		response.sendRedirect("https://www.tistory.com");
        	return;
        }

        filterChain.doFilter(request, response);
    }
    
}

 

Intercepter 에서도 마찬가지다.

Intercepter 의 preHandle 메소드에서 리다이렉트를 사용할때도 response 객체를 사용해야 하는데

아래와 같이 명시적으로 false 를 리턴해야 Controller 진입없이 리다이렉트만 정상적으로 수행된다.

public class TestInterceptor extends HandlerInterceptorAdaptor {
    
    @Override
    public boolean preHandler(
    	HttpServletRequest request
    	, HttpServletResponse response
        , Object handler) throws Exception {
        
        String uri = request.getRequestURI();
        if (uri.startsWith("/test/")) {
        	response.sendRedirect("https://www.tistory.com");
        	return false;
        }
        
        return true;
    }

    @Override
    public void postHandler(
    	HttpServletRequest request
    	, HttpServletResponse response
        , Object handler
        , ModelAndView modelAndView) throws Exception {
        
        System.out.println("post handle...");
    }
}

 

 

 

 

 

 

728x90

'Backend > Http+Servlet' 카테고리의 다른 글

URL 에 포함된 한글 파라미터 처리  (0) 2021.11.17
한글 인코딩과 new String, getBytes  (0) 2021.07.16
Contents-Type, Accept  (0) 2021.04.20
서버에서 클라이언트 Cookie 셋팅하기  (0) 2021.03.29
JSESSIONID  (0) 2021.03.29