#23 Servlet에서 JSP로 forward하기

2026. 6. 21. 17:51·Project/Memo Evolution

 

이번 단계에서는 Servlet이 직접 HTML을 출력하던 방식에서 JSP로 화면을 분리했다.

처음에는 Servlet 안에서 브라우저에 직접 HTML을 보냈다.

response.setContentType("text/html;charset=UTF-8");
response.getWriter().println("<h1>Servlet 메모장</h1>");
response.getWriter().println("<p>Servlet이 정상적으로 실행되었습니다.</p>");

이 방식은 Servlet이 요청 처리와 화면 출력을 모두 담당하는 구조다.

간단한 확인용 화면에서는 문제없지만, 화면이 길어질수록 Java 코드 안에 HTML 문자열이 계속 들어가게 된다.

그래서 이번 단계에서는 역할을 나누기 위해 JSP를 사용했다.

Servlet
→ 요청 처리 담당

JSP
→ HTML 화면 출력 담당

 

 

 

JSP 파일은 다음 위치에 만들었다.

servlet-jsp-memo/src/main/webapp/WEB-INF/views/memos.jsp

WEB-INF 안에 둔 이유는 브라우저가 JSP에 직접 접근하지 못하게 하기 위해서다.

브라우저가 직접 JSP 접근
→ 막음

Servlet을 통해 JSP로 이동
→ 허용

즉 사용자가 이런 주소로 JSP에 직접 들어가는 것이 아니라,

/WEB-INF/views/memos.jsp

항상 Servlet을 통해 들어가도록 했다.

/memos

이 구조가 Servlet이 흐름을 제어하고 JSP가 화면을 담당하는 방식에 더 가깝다.

 

Servlet 코드 변경

기존에는 Servlet이 직접 HTML을 출력했다.

response.getWriter().println("<h1>Servlet 메모장</h1>");

변경 후에는 JSP로 요청을 넘겼다.

request.getRequestDispatcher("/WEB-INF/views/memos.jsp")
        .forward(request, response);

전체 코드는 다음과 같다.

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {

    request.getRequestDispatcher("/WEB-INF/views/memos.jsp")
            .forward(request, response);
}

이제 /memos 요청이 들어오면 MemoServlet이 실행되고, 그 안에서 JSP로 이동한다.

 

다음 코드는 현재 요청을 서버 내부의 특정 JSP로 넘기기 위한 준비를 한다.

request.getRequestDispatcher("/WEB-INF/views/memos.jsp")

의미는 다음과 같다.

이 요청을 /WEB-INF/views/memos.jsp가 이어서 처리하게 하겠다.

즉 getRequestDispatcher()는 요청을 전달할 대상을 찾는 역할을 한다.

 

forward란 무엇인가

forward()는 실제로 요청을 JSP로 넘기는 실행 부분이다.

.forward(request, response);

여기서 중요한 점은 브라우저가 새로 요청하는 것이 아니라는 것이다.

브라우저가 새로 요청하는 것이 아니다.
서버 내부에서 Servlet → JSP로 이동한다.

그래서 브라우저 주소창은 그대로 유지된다.

http://localhost:8080/memos

하지만 서버 내부에서는 다음 흐름으로 이동한다.

/memos 요청
→ MemoServlet
→ /WEB-INF/views/memos.jsp

즉 사용자는 /memos로 접속했지만, 실제 화면 출력은 JSP가 담당한다.

 

request와 response는 누가 만드는가

처음에는 response가 블랙박스처럼 느껴졌다.

브라우저가 요청을 보내면 Tomcat이 먼저 두 객체를 만든다.

request
response

request는 브라우저가 보낸 요청 정보를 담고 있다.

요청 URL
요청 방식
파라미터
사용자가 보낸 값
Servlet이 담아둔 데이터

response는 브라우저에게 돌려줄 응답을 만들 때 사용한다.

상태 코드
헤더
Content-Type
응답 본문
출력 통로

Tomcat은 이 두 객체를 Servlet에게 넘긴다.

doGet(request, response)

 

response는 완성된 응답이 아니다

중요하게 정리한 부분은 이것이다.

처음에는 Tomcat이 완성된 response를 JSP에 넘기는 것처럼 생각했다.

하지만 정확히는 그렇지 않다.

흐름은 다음과 같다.

Tomcat이 비어 있는 response 객체를 만든다.
Servlet에게 request와 response를 넘긴다.
Servlet은 JSP로 forward한다.
JSP가 response 안에 HTML을 채운다.
Tomcat이 완성된 response를 브라우저로 보낸다.

즉 Tomcat이 화면 내용을 알아서 만들어주는 것이 아니다.

Tomcat은 응답 객체를 만들고, 최종적으로 브라우저에 보내는 역할을 한다.
응답의 내용은 Servlet이나 JSP가 채운다.

 

Servlet이 직접 출력하는 경우

처음 방식은 Servlet이 직접 response를 채우는 방식이었다.

response.getWriter().println("<h1>Servlet 메모장</h1>");

흐름은 다음과 같다.

Tomcat이 response 생성
→ Servlet이 response에 HTML 작성
→ Tomcat이 response를 브라우저에 전송

즉 Servlet이 직접 응답 본문을 작성한다.

 

JSP로 forward하는 경우

JSP 방식에서는 Servlet이 직접 HTML을 작성하지 않는다.

request.getRequestDispatcher("/WEB-INF/views/memos.jsp")
        .forward(request, response);

흐름은 다음과 같다.

Tomcat이 response 생성
→ Servlet이 response를 직접 채우지 않음
→ Servlet이 request와 response를 JSP로 넘김
→ JSP가 response에 HTML 작성
→ Tomcat이 response를 브라우저에 전송

차이는 이것이다.

Servlet 직접 출력
→ Servlet이 response를 채움

JSP forward
→ JSP가 response를 채움

 

JSP에서는 response가 안 보이는데 어떻게 응답할까

JSP 파일에는 보통 HTML만 작성한다.

<h1>Servlet/JSP 메모장</h1>
<p>JSP 화면이 정상적으로 출력되었습니다.</p>

겉으로 보면 response를 직접 쓰지 않는다.

하지만 Tomcat은 JSP를 내부적으로 Servlet 코드로 변환해서 실행한다.

개념적으로는 이런 코드로 바뀐다고 볼 수 있다.

out.write("<h1>Servlet/JSP 메모장</h1>");
out.write("<p>JSP 화면이 정상적으로 출력되었습니다.</p>");

여기서 out은 JSP가 제공하는 출력 객체다.
이 out은 내부적으로 response와 연결되어 있다.

즉 흐름은 다음과 같다.

JSP에 작성한 HTML
→ Tomcat이 내부적으로 out.write(...)로 변환
→ response body에 기록
→ 브라우저로 전송

그래서 JSP에서 직접 response.getWriter()를 쓰지 않아도 응답이 되는 것이다.

 

response에는 본문만 있는 것이 아니다

response에는 HTML 본문만 들어가는 것이 아니다.

상태 코드
헤더
Content-Type
쿠키
본문

같은 정보가 들어간다.

다만 JSP가 주로 채우는 것은 HTML 본문이다.
상태 코드나 헤더는 보통 Servlet에서 설정할 수 있다.

예를 들면 다음과 같다.

response.setStatus(HttpServletResponse.SC_OK);
response.setContentType("text/html;charset=UTF-8");

 

현재 코드에서 상태 코드와 Content-Type은 어떻게 처리될까

현재 Servlet에서는 이렇게만 작성했다.

request.getRequestDispatcher("/WEB-INF/views/memos.jsp")
        .forward(request, response);

그런데도 응답이 정상적으로 나온다.

이유는 다음과 같다.

상태 코드
→ 정상 처리 시 Tomcat이 기본적으로 200 OK 사용

Content-Type
→ JSP의 page 지시어에서 설정

HTML 본문
→ JSP가 생성

JSP 맨 위에는 이런 코드가 있다.

<%@ page contentType="text/html;charset=UTF-8" language="java" %>

이 지시어가 응답의 Content-Type을 설정한다.

즉 현재 구조에서는 다음처럼 처리된다.

상태 코드 200
→ Tomcat 기본값

Content-Type
→ JSP page 지시어

HTML 본문
→ JSP가 생성

 

request를 넘기는 이유

forward(request, response)에서 request를 넘기는 이유는 JSP가 Servlet이 받은 요청 정보를 이어서 사용해야 하기 때문이다.

나중에는 Servlet에서 다음처럼 데이터를 담을 수 있다.

request.setAttribute("memos", memoService.getMemos());

그러면 JSP에서 그 데이터를 꺼내 화면에 출력할 수 있다.

흐름은 다음과 같다.

Servlet이 request에 데이터 저장
→ forward
→ JSP가 request에서 데이터 꺼내 출력

즉 request는 Servlet과 JSP 사이에서 데이터를 전달하는 통로로도 사용된다.

 

response를 넘기는 이유

response를 넘기는 이유는 JSP가 최종 HTML 응답을 브라우저로 보내야 하기 때문이다.

JSP 코드에서는 response가 직접 보이지 않지만, JSP가 생성하는 HTML은 결국 response에 기록된다.

따라서 JSP가 같은 응답 객체를 이어서 사용해야 한다.

Servlet이 받은 response
→ JSP로 전달
→ JSP가 HTML을 response에 기록
→ Tomcat이 브라우저로 전송

forward와 redirect 차이

이번에는 forward를 사용했다.

forward(request, response)

forward는 서버 내부 이동이다.

브라우저는 /memos로 요청
서버 내부에서 JSP로 이동
주소창은 /memos 그대로
request 유지

반면 redirect는 브라우저에게 다시 요청하라고 시키는 방식이다.

response.sendRedirect("/memos");

흐름은 다음과 같다.

서버가 브라우저에게 /memos로 다시 가라고 응답
브라우저가 새 요청을 보냄
request 새로 만들어짐

현재는 Servlet이 받은 request와 response를 JSP가 이어서 사용해야 하므로 forward를 사용한다.

 

이번 단계의 전체 흐름은 다음과 같다.

브라우저가 /memos 요청
→ Tomcat이 request, response 생성
→ MemoServlet.doGet(request, response) 실행
→ Servlet이 getRequestDispatcher로 JSP 위치 지정
→ forward(request, response)로 JSP에 전달
→ JSP가 HTML을 response에 작성
→ Tomcat이 완성된 response를 브라우저에 전송

이제 Servlet이 직접 HTML을 쓰지 않고, JSP가 화면을 담당하게 되었다.

 

이번 단계에서는 Servlet과 JSP의 역할을 분리했다.

기존 구조는 다음과 같았다.

Servlet이 요청 처리와 HTML 출력 모두 담당

변경 후 구조는 다음과 같다.

Servlet
→ 요청 처리와 흐름 제어 담당

JSP
→ HTML 화면 출력 담당

`request.getRequestDispatcher(...).forward(request, response)`는 단순히 외워야 하는 코드가 아니라, 다음 의미를 가진다.

현재 요청과 응답을 유지한 채
서버 내부에서 JSP에게 화면 출력을 맡긴다.

그리고 response는 완성된 결과물이 아니라, 브라우저로 나갈 응답을 담는 객체다.

Tomcat이 response를 만든다.
Servlet 또는 JSP가 response를 채운다.
Tomcat이 최종 response를 브라우저로 보낸다.

이 구조를 이해하니 Servlet/JSP가 블랙박스처럼 느껴지는 부분이 조금 줄었다.

다음 단계에서는 Servlet에서 메모 데이터를 request에 담고, JSP에서 그 데이터를 출력하는 방식으로 확장해볼 예정이다.

'Project > Memo Evolution' 카테고리의 다른 글

#24 Servlet과 JSP에서 request는 어떻게 사용될까  (0) 2026.06.22
#22 Tomcat으로 Servlet 실행하기  (0) 2026.06.21
#21 Java 콘솔 메모장: MemoService로 로직 분리하기  (0) 2026.06.21
#20 Java 콘솔 메모장 : String 배열에서 Memo 클래스로 변경하기  (0) 2026.06.21
#19 Java 콘솔 메모장: CRUD기능 구현하기  (0) 2026.06.20
'Project/Memo Evolution' 카테고리의 다른 글
  • #24 Servlet과 JSP에서 request는 어떻게 사용될까
  • #22 Tomcat으로 Servlet 실행하기
  • #21 Java 콘솔 메모장: MemoService로 로직 분리하기
  • #20 Java 콘솔 메모장 : String 배열에서 Memo 클래스로 변경하기
sqaxe1
sqaxe1
woojoo-devlog 님의 블로그 입니다.
  • sqaxe1
    Woojoo's Devlog
    sqaxe1
  • 전체
    오늘
    어제
    • 분류 전체보기 (148)
      • Backend (9)
        • Servlet (7)
        • Spring (2)
      • Frontend (1)
      • CS (0)
      • Book (33)
        • 자바 웹 프로그래밍 Next Step (30)
        • 테스트 주도 개발: 고품질 쾌속개발을 위한 TDD.. (1)
        • 성공과 실패를 결정하는 1%의 네트워크 원리 (2)
      • Engineering (0)
        • Testing (0)
      • Infra (6)
        • AWS (6)
      • Java (4)
      • Network (1)
      • 김영한 (28)
        • 자바 입문 (8)
        • 실전 자바 - 기본편 (6)
        • 실전 자바 - 중급편 (10)
        • 실전 자바 - 고급편 (4)
      • Web (39)
        • Web Basics (39)
      • Project (24)
        • NeoSquare (0)
        • Memo Evolution (24)
      • 정보처리기사 (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    개발서적
    java
    aws
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
sqaxe1
#23 Servlet에서 JSP로 forward하기
상단으로

티스토리툴바