Learning/Servlet & JPA / / 2025. 3. 18. 17:41

Servlet 요청 이동: getRequestDispatcher().forward() vs. sendRedirect()

Servlet 요청 이동: getRequestDispatcher().forward() vs. sendRedirect() 완벽 비교

웹 애플리케이션을 개발하다 보면 사용자의 요청을 처리한 후 다른 페이지로 이동시켜야 하는 경우가 많습니다. Java Servlet 환경에서는 이러한 요청 이동을 처리하는 대표적인 방법으로 getRequestDispatcher().forward()sendRedirect() 가 있습니다. 얼핏 보면 비슷해 보이지만, 내부적인 동작 방식과 사용 목적에는 분명한 차이가 있습니다. 이번 글에서는 이 두 가지 방식의 차이점을 명확하게 이해하고, 어떤 상황에서 어떤 방법을 선택해야 하는지 자세히 알아보겠습니다.

 

요청 이동, 왜 필요할까요?

웹 애플리케이션은 다양한 기능을 제공하기 위해 여러 개의 페이지나 서블릿으로 구성됩니다. 사용자의 상호작용에 따라 적절한 흐름을 만들어내기 위해 요청 이동은 필수적입니다. 예를 들어,

  • 회원가입 성공 후 환영 페이지로 이동
  • 로그인 실패 시 에러 메시지와 함께 로그인 페이지로 다시 이동
  • 상품 목록 페이지에서 특정 상품 상세 페이지로 이동

이러한 시나리오에서 요청 이동은 사용자 경험을 향상시키고 애플리케이션의 흐름을 자연스럽게 만들어줍니다.

 

getRequestDispatcher().forward(): 서버 내부적인 이동

getRequestDispatcher().forward() 는 현재 요청을 처리하던 서블릿이 작업을 완료하지 않고, 다른 서블릿이나 JSP 페이지에게 요청 처리를 내부적으로 위임하는 방식입니다. 마치 회사에서 한 팀의 담당자가 다른 팀에게 업무를 넘기는 것과 비슷하다고 생각할 수 있습니다.

 

동작 방식:

  1. 클라이언트 (웹 브라우저)가 특정 URL로 요청을 보냅니다.
  2. 웹 서버는 해당 요청을 처리할 서블릿에게 전달합니다.
  3. 서블릿은 getRequestDispatcher() 를 사용하여 이동할 다른 리소스 (서블릿 또는 JSP)에 대한 RequestDispatcher 객체를 얻습니다. 이때 이동할 리소스의 경로는 서버 내부 경로를 사용합니다.
  4. 서블릿은 얻어온 RequestDispatcher 객체의 forward() 메소드를 호출하면서 현재의 요청(HttpServletRequest) 객체와 응답(HttpServletResponse) 객체를 함께 전달합니다.
  5. 웹 서버는 클라이언트에게 응답을 보내기 전에 내부적으로 지정된 리소스에게 요청 처리를 넘깁니다.
  6. 클라이언트의 웹 브라우저는 여전히 최초 요청 URL을 표시합니다. 이동이 서버 내부적으로 이루어졌기 때문에 브라우저는 이동 사실을 알지 못합니다.

코드 예시:

// 서블릿 A
@WebServlet("/servletA")
public class ServletA extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        request.setAttribute("message", "Servlet A에서 전달하는 메시지");
        RequestDispatcher dispatcher = request.getRequestDispatcher("/view/result.jsp"); // 내부 경로 사용
        dispatcher.forward(request, response);
    }
}

// result.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>결과 페이지</title>
</head>
<body>
    <h1>결과 페이지</h1>
    <p>${message}</p>
</body>
</html>

위 예시에서 클라이언트가 /servletA 로 요청을 보내면 ServletA 는 "message" 라는 속성을 요청 객체에 저장하고, /view/result.jsp 로 포워딩합니다. 브라우저의 주소창에는 여전히 /servletA 가 표시되지만, 실제 내용은 result.jsp 에서 렌더링된 결과가 나타납니다.

 

forward() 의 특징:

  • 서버 측 이동: 이동이 서버 내부적으로 이루어집니다.
  • URL 유지: 클라이언트의 브라우저 URL은 변경되지 않습니다.
  • 요청 및 응답 객체 공유: 원래 요청 객체와 응답 객체가 이동되는 리소스에서 그대로 사용 가능합니다. 따라서 요청 시 설정했던 속성(Attribute) 등을 전달할 수 있습니다.
  • 효율성: 새로운 HTTP 요청을 발생시키지 않으므로 비교적 효율적입니다.

 

주요 사용 사례:

  • 컨트롤러 서블릿에서 요청을 받아 비즈니스 로직을 처리한 후, 결과를 보여주는 JSP 페이지로 이동할 때
  • 여러 서블릿이 하나의 요청 처리 흐름을 분담할 때

 

sendRedirect(): 클라이언트에게 새로운 요청 지시

sendRedirect() 는 현재 서블릿이 클라이언트에게 새로운 URL로 다시 요청을 보내도록 응답하는 방식입니다. 마치 길을 묻는 사람에게 "저쪽으로 가서 다시 물어보세요" 라고 안내하는 것과 비슷합니다.

 

동작 방식:

  1. 클라이언트가 특정 URL로 요청을 보냅니다.
  2. 웹 서버는 해당 요청을 처리할 서블릿에게 전달합니다.
  3. 서블릿은 sendRedirect() 메소드를 호출하면서 이동할 새로운 URL을 파라미터로 전달합니다. 이때 새로운 URL은 절대 경로 또는 상대 경로를 사용할 수 있습니다.
  4. 웹 서버는 클라이언트에게 HTTP 응답 (상태 코드 302 Found 또는 307 Temporary Redirect)을 보냅니다. 이 응답에는 Location 헤더에 새로운 URL 정보가 담겨 있습니다.
  5. 클라이언트는 이 응답을 받고, Location 헤더에 명시된 새로운 URL로 새로운 HTTP 요청을 보냅니다.
  6. 웹 서버는 새로 받은 요청에 따라 해당 리소스를 처리하고 응답을 클라이언트에게 보냅니다.
  7. 클라이언트의 웹 브라우저는 새로운 URL을 주소창에 표시합니다.

 

코드 예시:

// 서블릿 B
@WebServlet("/servletB")
public class ServletB extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 어떤 처리...
        response.sendRedirect("/success.html"); // 새로운 URL로 리다이렉트
    }
}

// success.html (예시)
<!DOCTYPE html>
<html>
<head>
    <title>성공</title>
</head>
<body>
    <h1>성공적으로 처리되었습니다!</h1>
</body>
</html>

위 예시에서 클라이언트가 /servletB 로 요청을 보내면 ServletB 는 어떤 처리를 수행한 후 /success.html 로 리다이렉트합니다. 브라우저는 /servletB 요청에 대한 응답으로 리다이렉트 정보를 받고, 자동으로 /success.html 로 새로운 요청을 보냅니다. 따라서 브라우저 주소창에는 /success.html 이 표시됩니다.

 

sendRedirect() 의 특징:

  • 클라이언트 측 이동: 실제 이동은 클라이언트의 웹 브라우저에 의해 이루어집니다.
  • URL 변경: 클라이언트의 브라우저 URL이 새로운 URL로 변경됩니다.
  • 새로운 요청: 리다이렉트될 때마다 새로운 HTTP 요청이 발생합니다. 따라서 원래 요청 시 설정했던 속성(Attribute) 등은 유지되지 않습니다.
  • 덜 효율적: 새로운 HTTP 요청을 발생시키므로 forward() 에 비해 상대적으로 덜 효율적입니다.

 

주요 사용 사례:

  • 폼 제출 후 결과 페이지로 이동하여 새로고침 시 데이터가 중복 제출되는 것을 방지할 때 (Post-Redirect-Get 패턴)
  • 사용자를 다른 웹사이트나 애플리케이션의 다른 영역으로 이동시킬 때
  • 로그인 성공 후 메인 페이지로 이동할 때

 

forward() vs. sendRedirect(): 핵심 차이점 비교

특징 getRequestDispatcher().forward() sendRedirect()
이동 방식 서버 측 클라이언트 측
URL 변경 여부 No Yes
요청 객체 공유 Yes No (새로운 요청)
효율성 비교적 높음 비교적 낮음 (새로운 HTTP 요청 발생)
주요 사용 사례 내부적인 페이지 이동 (컨트롤러 -> 뷰) 외부 또는 새로운 요청이 필요한 이동

 

어떤 것을 선택해야 할까요?

어떤 방법을 선택할지는 여러분의 애플리케이션의 요구 사항과 상황에 따라 달라집니다.

  • forward() 를 선택해야 하는 경우:
    • 요청 처리 결과를 다른 페이지에서 보여줘야 하지만, URL을 변경하고 싶지 않을 때
    • 현재 요청에 대한 정보를 다음 페이지에서도 그대로 사용해야 할 때
    • 서버 내부적으로 효율적인 페이지 이동을 원할 때 (예: 컨트롤러에서 뷰로 이동)
  • sendRedirect() 를 선택해야 하는 경우:
    • 사용자를 완전히 새로운 URL로 이동시키고 싶을 때 (예: 외부 사이트, 다른 애플리케이션 영역)
    • 폼 데이터가 성공적으로 처리된 후, 사용자가 결과 페이지를 새로고침하더라도 데이터가 다시 제출되는 것을 방지하고 싶을 때 (Post-Redirect-Get 패턴)
    • 보안상의 이유로 URL을 변경해야 할 때
  •  

결론

getRequestDispatcher().forward()sendRedirect() 는 웹 애플리케이션 개발에서 자주 사용되는 중요한 개념입니다. 각 방식의 동작 방식과 특징을 정확히 이해하고, 상황에 맞는 적절한 방법을 선택하는 것이 효율적이고 안정적인 웹 애플리케이션 개발의 핵심입니다. 이제 여러분은 이 두 가지 방법을 명확하게 구분하고, 실제 프로젝트에서 적절하게 활용할 수 있을 것입니다.

  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유