브라우저가 할 수 있는 일은 딱 하나
브라우저의 역할은 매우 단순하다.
서버에 요청을 보내고, 서버가 보내준 응답(문자들)을 화면에 그리는 것
브라우저는 서버 컴퓨터 내부에 있는 파일을 직접 열 수 없다.
- /user/updateForm.jsp 파일을 “읽어서” 여는 능력이 없다
- 서버의 파일 시스템에 접근할 수 없다
- JSP, Java, DB 같은 것은 전혀 모른다
브라우저가 이해할 수 있는 것은 오직 HTML, CSS, JavaScript로 이루어진 문자열뿐이다.
JSP는 “파일”이지만 목적은 “프로그램”이다
JSP는 파일 형태로 존재하지만, 단순한 정적 HTML 파일이 아니다.
JSP 안에는 다음과 같은 것들이 들어간다.
- ${user.name} 같은 EL 표현식
- <c:forEach> 같은 JSTL 태그
- <% %> 같은 자바 코드(있을 수도 있다)
이것들은 그대로 브라우저에 보내면 브라우저가 절대 이해하지 못한다.
브라우저는 ${user.name}을 실행할 수 없다.
반복문도, 자바 코드도 모른다.
그래서 반드시 서버가 JSP를 실행해야 한다.
서버가 JSP를 실행해서
${user.name}을 실제 값(예: "철수")으로 바꾼
완성된 HTML 문자열을 만들어야 한다.
forward란 무엇인가
forward는 “페이지 이동”이 아니다.
정확히 말하면 서버 내부에서 처리 담당자를 바꾸는 동작이다.
실제 흐름을 그대로 따라가 보자
(1) 서블릿에서 데이터 조회
User user = DataBase.findByUser(userId);
(2) request에 데이터 저장
req.setAttribute("user", user);
이때 req는 이번 요청 하나를 위한 서버 메모리 상자다.
브라우저로 가는 것이 아니다.
(3) JSP로 넘길 준비
RequestDispatcher rd = req.getRequestDispatcher("/user/updateForm.jsp");
이 코드는 말 그대로다.
“이 JSP로 forward할 수 있는 통로를 하나 만들어 달라”
아직 실행은 아니다.
(4) forward 실행
rd.forward(req, resp);
이 한 줄이 의미하는 것은 딱 이것이다.
“지금 처리 중인 요청(req)과 응답(resp)을 그대로 들고
JSP로 넘어가서 JSP가 응답을 만들어라”
왜 forward는 “파일로 이동”이 아닌가
만약 “파일로 이동”이라면 브라우저가 그 파일을 직접 읽어야 한다.
하지만 현실은 이렇다.
- 브라우저는 JSP 파일을 읽지 않는다
- 서버가 JSP를 실행한다
- JSP 실행 결과로 HTML 문자열을 만든다
- 그 HTML을 resp에 담아 브라우저로 보낸다
예를 들어 JSP에 다음 코드가 있다.
<input name="name" value="${user.name}">
서버에서 JSP가 실행되면 결과는 이렇게 바뀐다.
<input name="name" value="철수">
브라우저는 이 최종 HTML만 받는다.
`${user.name}`이라는 표현은 이미 서버에서 사라진 상태다.
주소창에 JSP 경로가 보이는 것처럼 느껴지는 이유
“주소창에 /user/updateForm.jsp가 보이는대?”
실제로 브라우저가 요청한 URL은 보통 이런 형태다.
/user/updateForm?userId=woojoo
서버가 내부에서 forward로 JSP를 실행해도,
- 브라우저는 그 사실을 모른다
- 새로운 요청이 발생하지 않는다
- 주소창 URL은 바뀌지 않는다
즉,
forward는 브라우저에게 새 URL로 이동하라고 지시하지 않는다.
서버 내부에서만 조용히 처리 담당을 넘긴다.
forward를 한 문장으로 정리하면
forward(req, resp)는
“서블릿이 준비한 데이터를 req에 담아둔 채로
JSP에게 넘겨서 JSP가 최종 HTML을 만들고
그 결과를 resp로 브라우저에 보내게 하는 것”이다.
Dispatcher와 forward의 정확한 역할 분리
req.getRequestDispatcher("/user/updateForm.jsp");
- JSP로 넘길 통로(Dispatcher) 를 얻는 것
- 아직 실행은 아니다
rd.forward(req, resp);
- req, resp를 그대로 유지한 채
- JSP 실행을 시작하는 시점
JSP에서 resp는 어디에 쓰이는가
JSP 코드 안에서는 resp.getWriter() 같은 코드가 보이지 않는다.
그래서 “resp가 어디서 쓰이냐”는 혼란이 생긴다.
정답은
JSP 파일에 적힌 모든 HTML이 곧 resp로 쓰인다.
예를 들어 JSP에 다음이 있다.
<label for="name">이름</label> <input value="${user.name}">
JSP가 실행되면 서버 내부에서는 개념적으로 이런 코드로 바뀐다.
out.write("<label for=\"name\">이름</label>");
out.write("<input value=\"철수\">");
여기서 out은 사실상 `resp.getWriter()`에 연결된 출력 스트림이다.
즉,
- JSP의 HTML 한 줄 한 줄
- EL로 치환된 값들
- <input>, <table>, <div> 전부
모두 resp를 통해 브라우저로 흘러간다.
“resp를 쓴다”의 정확한 의미
서블릿에서는 이렇게 직접 쓴다.
resp.getWriter().println("<h1>Hello</h1>");
JSP에서는 이렇게 쓴다.
<h1>Hello</h1>
하지만 결과는 완전히 같다.
JSP가 출력한 결과(HTML 전체)가
톰캣에 의해 자동으로 resp에 쓰인다.
정리
- 브라우저는 서버 파일을 열 수 없다
- JSP는 브라우저용 파일이 아니라 서버에서 실행되는 프로그램이다
- forward는 “페이지 이동”이 아니다
- forward는 서버 내부에서 처리 담당을 JSP로 넘기는 것이다
- JSP는 req에 담긴 데이터를 사용해 HTML을 만든다
- JSP가 만든 HTML 전체가 resp로 브라우저에 전달된다
브라우저는 HTML만 받고,
JSP 실행과 데이터 치환은 전부 서버에서 끝난다.
'Backend > Servlet' 카테고리의 다른 글
| 서블릿이 생성되고 요청이 처리되는 전체 흐름 (0) | 2026.02.08 |
|---|---|
| 멀티스레드 환경에서 Servlet 사용 (0) | 2026.02.06 |
| Servlet Container와 Servlet의 관계 (0) | 2026.02.05 |
| RequestMapping static Map은 괜찮은 이유 (0) | 2026.02.05 |
| 서블릿에서의 static (0) | 2026.02.05 |