웹 애플리케이션에서 가장 헷갈리는 지점 중 하나는
“데이터는 어디에 저장하고, 화면은 누가 그리고, 요청은 어떻게 전달되는가”다.
이 서블릿이 하는 일 한 줄 요약
@WebServlet("/user/list")
public class ListUserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setAttribute("users", DataBase.findAll());
RequestDispatcher rd = req.getRequestDispatcher("/user/list.jsp");
rd.forward(req, resp);
}
}
이 서블릿의 역할은 다음 한 문장으로 요약된다.
DB에서 사용자 목록을 조회해서, JSP가 화면을 그릴 수 있도록 request에 담아 넘긴다
즉,
- 데이터 준비는 서블릿
- 화면 렌더링은 JSP
이 역할 분리가 핵심이다.
DataBase.findAll()은 어디에 저장되는가?
req.setAttribute("users", DataBase.findAll());
여기서 “저장은 다 DB에 하는 거 아닌가?" "request에도 저장할 수 있나?"라는 의문이 들었다.
DB 저장과 request 저장은 목적이 완전히 다르다
DB 저장
- 목적: 영구 보관
- 서버 재시작해도 남는다
- 다른 요청, 다른 사용자도 접근 가능
- 예시:
- 회원가입
- 게시글 작성
- 주문 저장
request 저장 (setAttribute)
- 목적: 한 번의 요청 처리 동안 데이터 전달
- 같은 요청 흐름 안에서만 유효
- 다른 요청에서는 절대 보이지 않는다
- 예시:
- “이 페이지에 뿌릴 사용자 목록”
- “에러 메시지”
- “조회 결과”
즉,
DB는 저장소, request는 전달용 가방이다
request에 데이터를 넣는 이유
req.setAttribute("users", DataBase.findAll());
이 줄의 의미를 정확히 말하면 이렇다.
- DB에서 전체 사용자 목록(List<User>)을 가져온다
- 그 결과를
- 현재 요청(HttpServletRequest)에
- "users"라는 이름으로 붙인다
이 데이터는 다음 특징을 가진다.
- 같은 요청 안에서만 유효하다
- forward로 넘기면 그대로 따라간다
- 응답이 끝나면 바로 사라진다
즉,
“JSP가 꺼내 쓸 데이터를 미리 준비해두는 단계”이다
getRequestDispatcher는 무엇인가
RequestDispatcher rd = req.getRequestDispatcher("/user/list.jsp");
여기서 RequestDispatcher는 데이터를 담는 객체가 아니다.
RequestDispatcher의 정체
RequestDispatcher는 다음 역할만 한다.
“이 요청을 어느 리소스로 넘길지 알고 있는 실행자”
즉, rd 안에 들어있는 것은:
- 이동 대상 경로 (/user/list.jsp)
- 서버 내부 요청 전달 로직
❌ 들어있지 않은 것
- 데이터
- users 목록
- request 내용
데이터는 전부 req 안에 있다.
rd.forward(req, resp)는 정확히 뭐 하는 건가
rd.forward(req, resp);
이 한 줄이 실제로 하는 일은 다음과 같다.
- 서버 내부에서 /user/list.jsp를 실행한다
- 같은 req 객체를 그대로 넘긴다
- 같은 resp 객체를 그대로 넘긴다
- JSP가 HTML을 생성해서 resp에 써 넣는다
- 최종 응답을 브라우저로 보낸다
여기서 핵심 포인트는 세 가지다.
1) 서버 내부 이동이다
- 브라우저는 모른다
- URL은 바뀌지 않는다
2) request가 유지된다
- req.setAttribute("users", ...) 그대로 사용 가능
- JSP에서 ${users}로 꺼내 쓸 수 있다
3) 응답은 아직 비어 있다
- 서블릿은 resp에 아무것도 안 썼다
- JSP가 resp에 HTML을 써서 채운다
forward 시점의 상태
- req
- 이미 데이터가 채워져 있다
- users, 기타 attribute들이 들어 있다
- resp
- 상태 코드/헤더만 준비된 상태
- 본문(body)은 아직 비어 있다
그래서 역할이 이렇게 나뉜다.
서블릿은 req를 채우고,
JSP는 resp에 HTML을 쓴다
sendRedirect와 forward의 결정적 차이
resp.sendRedirect("/user/list");
이것도 “넘기는 것”처럼 보이지만 forward와 완전히 다르다.
forward
- 서버 내부 이동
- 같은 request 유지
- request attribute 유지
- JSP 렌더링에 사용
sendRedirect
- 브라우저에게 “새 요청 보내라”라고 지시
- URL 변경
- 새 request 생성
- 기존 request attribute 전부 사라짐
그래서 패턴이 이렇게 갈린다.
- 목록 화면, 상세 화면 → forward
- 회원가입 완료, 수정 완료 → redirect
한 줄 요약:
서블릿이 데이터 준비 → request에 담음 → JSP로 넘김 → JSP가 화면 생성
정리
- DB 저장 ≠ request 저장
- request는 뷰로 데이터 전달용
- RequestDispatcher는 이동 대상만 알고 있는 실행자
- forward는 같은 요청 유지
- JSP는 resp에 HTML을 쓰는 역할
- 서블릿은 화면을 그리지 않는다
출처 : 《자바 웹 프로그래밍 Next Step》, 박재성, 로드북
'Book > 자바 웹 프로그래밍 Next Step' 카테고리의 다른 글
| 6장_ 요구사항1: 개인정보 수정 (0) | 2026.02.06 |
|---|---|
| 6장_ : ListUser 화면 구현 (0) | 2026.02.06 |
| 5장_ : 서블릿 컨테이너가 하는 일: 생명주기와 인스턴스 생성 (0) | 2026.02.05 |
| 5장_ : Servlet으로 Hello World 출력하기 (0) | 2026.02.05 |
| 5장_: 임베디드 톰캣으로 웹 서버 띄우기 (0) | 2026.02.05 |
