Servlet 요청 이동: getRequestDispatcher().forward() vs. sendRedirect() 완벽 비교
웹 애플리케이션을 개발하다 보면 사용자의 요청을 처리한 후 다른 페이지로 이동시켜야 하는 경우가 많습니다. Java Servlet 환경에서는 이러한 요청 이동을 처리하는 대표적인 방법으로 getRequestDispatcher().forward()
와 sendRedirect()
가 있습니다. 얼핏 보면 비슷해 보이지만, 내부적인 동작 방식과 사용 목적에는 분명한 차이가 있습니다. 이번 글에서는 이 두 가지 방식의 차이점을 명확하게 이해하고, 어떤 상황에서 어떤 방법을 선택해야 하는지 자세히 알아보겠습니다.
요청 이동, 왜 필요할까요?
웹 애플리케이션은 다양한 기능을 제공하기 위해 여러 개의 페이지나 서블릿으로 구성됩니다. 사용자의 상호작용에 따라 적절한 흐름을 만들어내기 위해 요청 이동은 필수적입니다. 예를 들어,
- 회원가입 성공 후 환영 페이지로 이동
- 로그인 실패 시 에러 메시지와 함께 로그인 페이지로 다시 이동
- 상품 목록 페이지에서 특정 상품 상세 페이지로 이동
이러한 시나리오에서 요청 이동은 사용자 경험을 향상시키고 애플리케이션의 흐름을 자연스럽게 만들어줍니다.
getRequestDispatcher().forward()
: 서버 내부적인 이동
getRequestDispatcher().forward()
는 현재 요청을 처리하던 서블릿이 작업을 완료하지 않고, 다른 서블릿이나 JSP 페이지에게 요청 처리를 내부적으로 위임하는 방식입니다. 마치 회사에서 한 팀의 담당자가 다른 팀에게 업무를 넘기는 것과 비슷하다고 생각할 수 있습니다.
동작 방식:
- 클라이언트 (웹 브라우저)가 특정 URL로 요청을 보냅니다.
- 웹 서버는 해당 요청을 처리할 서블릿에게 전달합니다.
- 서블릿은
getRequestDispatcher()
를 사용하여 이동할 다른 리소스 (서블릿 또는 JSP)에 대한RequestDispatcher
객체를 얻습니다. 이때 이동할 리소스의 경로는 서버 내부 경로를 사용합니다. - 서블릿은 얻어온
RequestDispatcher
객체의forward()
메소드를 호출하면서 현재의 요청(HttpServletRequest
) 객체와 응답(HttpServletResponse
) 객체를 함께 전달합니다. - 웹 서버는 클라이언트에게 응답을 보내기 전에 내부적으로 지정된 리소스에게 요청 처리를 넘깁니다.
- 클라이언트의 웹 브라우저는 여전히 최초 요청 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로 다시 요청을 보내도록 응답하는 방식입니다. 마치 길을 묻는 사람에게 "저쪽으로 가서 다시 물어보세요" 라고 안내하는 것과 비슷합니다.
동작 방식:
- 클라이언트가 특정 URL로 요청을 보냅니다.
- 웹 서버는 해당 요청을 처리할 서블릿에게 전달합니다.
- 서블릿은
sendRedirect()
메소드를 호출하면서 이동할 새로운 URL을 파라미터로 전달합니다. 이때 새로운 URL은 절대 경로 또는 상대 경로를 사용할 수 있습니다. - 웹 서버는 클라이언트에게 HTTP 응답 (상태 코드 302 Found 또는 307 Temporary Redirect)을 보냅니다. 이 응답에는
Location
헤더에 새로운 URL 정보가 담겨 있습니다. - 클라이언트는 이 응답을 받고,
Location
헤더에 명시된 새로운 URL로 새로운 HTTP 요청을 보냅니다. - 웹 서버는 새로 받은 요청에 따라 해당 리소스를 처리하고 응답을 클라이언트에게 보냅니다.
- 클라이언트의 웹 브라우저는 새로운 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()
는 웹 애플리케이션 개발에서 자주 사용되는 중요한 개념입니다. 각 방식의 동작 방식과 특징을 정확히 이해하고, 상황에 맞는 적절한 방법을 선택하는 것이 효율적이고 안정적인 웹 애플리케이션 개발의 핵심입니다. 이제 여러분은 이 두 가지 방법을 명확하게 구분하고, 실제 프로젝트에서 적절하게 활용할 수 있을 것입니다.
'Learning > Servlet & JPA' 카테고리의 다른 글
@GeneratedValue (0) | 2025.04.16 |
---|---|
Servlet/JSP 경험을 바탕으로 스프링 이해하기 (0) | 2025.03.19 |
웹 어플리케이션 개발을 위해 내가 더 알아야할 기초 개념 (0) | 2025.03.18 |
Servlet (0) | 2025.03.11 |