앞에서 param은 “요청 파라미터”를 EL로 읽는 방식이라고 했다.
하지만 실제 화면에서는 파라미터만 출력하는 경우는 드물다.
보통은 이런 흐름이 많다.
- 서블릿이 로직을 처리한다(데이터 조회/가공)
- 화면에 필요한 값을 만든다
- 그 값을 JSP로 넘긴다
- JSP는 화면에 출력만 한다
이 구조가 서블릿+JSP의 기본 MVC 형태로 이어진다.
// ================================
// [예시] 서블릿이 데이터를 준비해서 JSP로 넘기는 전형적인 흐름
// - request.setAttribute("message", ...) 로 "요청 범위"에 데이터를 저장한다
// - RequestDispatcher.forward(...) 로 JSP에 넘긴다
// ================================
@WebServlet("/hello-jsp")
public class HelloJspController extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
// 1) 컨트롤러(서블릿)가 화면에 필요한 데이터를 준비한다
String message = "Hello from Servlet";
// 2) request 영역에 저장한다 (요청 1회 동안만 유효)
req.setAttribute("message", message);
// 3) JSP로 forward 한다 (같은 request/response를 들고 이동)
req.getRequestDispatcher("/WEB-INF/views/hello.jsp")
.forward(req, resp);
}
}
request.setAttribute는 “요청 범위 데이터 저장”이다
서블릿이 JSP로 데이터를 전달할 때 가장 많이 쓰는 방식이 이것이다.
- request.setAttribute(key, value)
여기서 포인트는 두 가지이다.
- key는 문자열이다
- value는 객체면 뭐든 들어갈 수 있다
즉 request는 “현재 요청 동안만 쓰는 저장소”로도 쓸 수 있다.
forward는 같은 request/response를 들고 JSP로 이동한다
서블릿은 보통 RequestDispatcher로 JSP로 넘긴다.
- request.getRequestDispatcher("...").forward(req, resp)
여기서 forward는 이런 의미이다.
- 지금까지 response에 쓴 내용은 무시하고
- JSP가 만드는 내용으로 최종 응답을 만든다
- 그리고 중요한 점은 request/response 객체는 그대로 유지된다는 것이다
즉 서블릿이 request에 넣어둔 값은
forward된 JSP에서도 그대로 꺼낼 수 있다.
JSP EL은 request에 저장된 attribute를 바로 읽을 수 있다
서블릿에서 이렇게 저장했다고 하자.
- req.setAttribute("message", "Hello");
JSP에서는 그냥 이렇게 출력하면 된다.
- ${message}
여기서 중요한 점은 EL이 “Model 객체를 읽는다”가 아니라,
request에 들어있는 attribute를 읽는다는 것이다.
즉, ${message}는 내부적으로
- request에서 message라는 이름의 attribute가 있나 찾고
- 있으면 그 값을 출력하는 방식이다
EL 스코프(scope): 값을 어디서 찾는가
EL은 `${message}` 같은 표현을 만나면
단순히 request만 보는 게 아니라 “범위(scope)”를 순서대로 훑는다.
대표적인 스코프는 4개이다.
- pageScope
- requestScope
- sessionScope
- applicationScope
스코프의 우선순위
EL이 `${name}`을 찾을 때는 보통 이 순서로 찾는다.
- pageScope
- requestScope
- sessionScope
- applicationScope
즉 같은 이름의 값이 여러 곳에 있으면
우선순위가 높은 쪽이 먼저 잡힌다.
그래서 실전에서는 “어디에 들어있는 값인지”가 헷갈릴 수 있다.
스코프를 명시해서 꺼낼 수도 있다
헷갈리면 scope를 명확하게 써서 접근할 수도 있다.
- ${requestScope.message}
- ${sessionScope.user}
- ${applicationScope.appName}
이렇게 쓰면 EL이 어디서 값을 찾는지 명확해진다.
각 스코프가 의미하는 “수명”이 다르다
스코프는 결국 “언제까지 살아있냐”의 차이이다.
- requestScope: 요청 1번 동안만 유지(응답 끝나면 사라짐)
- sessionScope: 사용자(브라우저) 단위로 유지(세션 만료까지 유지)
- applicationScope: 애플리케이션 전체 공유(서버 내려갈 때까지 유지)
즉 같은 “값 저장”이라도 저장 위치에 따라 의미가 달라진다.
핵심 정리
- 서블릿은 request.setAttribute로 JSP에 넘길 데이터를 저장한다
- forward를 하면 같은 request/response를 들고 JSP로 이동한다
- JSP EL의 ${name}은 스코프를 순서대로 탐색해서 값을 찾는다
- request/session/application은 수명이 다르므로 저장 위치를 의도적으로 선택해야 한다
'Web > Web Basics' 카테고리의 다른 글
| [서블릿과 JSP] 8. 톰캣(서블릿 컨테이너)은 실제로 무슨 일을 하는가 (0) | 2026.03.29 |
|---|---|
| [서블릿과 JSP] 7. JSTL은 왜 필요하고, <c:forEach>는 무엇인가 (0) | 2026.03.29 |
| [서블릿과 JSP] 5. request.getParameter()를 JSP에서 쓰는 방법 (0) | 2026.03.29 |
| [서블릿과 JSP] 4. JSP는 왜 필요한가 (0) | 2026.03.29 |
| [서블릿과 JSP] 3. HttpServletRequest/HttpServletResponse (0) | 2026.03.29 |