🍁생명주기
내장 객체에 저장소를 제공하는데, pageContext, request, session, application 중에 어떤 것을 사용해야 하는지 의문이 생길 수 있다. 이때 내장 객체의 생명주기를 고려하면 된다.
내가 저장하고 사용할 데이터를 어느 기간 동안 사용할지에 대해 결정하고, 내장 객체가 어느 기간 동안 객체가 유지되는지에 대한 생명주기를 고려하여 일치하는 것을 찾는다.
- ex19_scope_1: 데이터 입력 페이지
- ex19_scope_2: 데이터 수신 및 처리 페이지
각 방법으로 데이터를 전달하는 과정을 살펴보면서 내장 객체의 생명주기에 대해 알아보도록 하자.
ex19_scope_1
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
//1. 지역 변수 > 실패
int a = 10;
/* 자바로 페이지 이동 */
//response.sendRedirect("ex19_scope_2.jsp?a=" + a);
//3. pageContext객체 > 실패
pageContext.setAttribute("c", 30);
//4. requesst 객체
request.setAttribute("d", 40);
//5. session 객체
session.setAttribute("e", 50);
//6. application 객체
application.setAttribute("f", 60);
//response.sendRedirect("ex19_scope_2.jsp");
pageContext.forward("ex19_scope_2.jsp?");
%>
<%!
//2. 멤버 변수 > 실패
int b = 20;
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="http://pinnpublic.dothome.co.kr/cdn/example-min.css">
<style>
</style>
</head>
<body>
<h1>첫 번째 페이지</h1>
<!-- 클라이언트 코드로 페이지 이동 -->
<!-- 1 링크로 이동 -->
<a href="ex19_scope_2.jsp?a=<%= a %>">두 번째 페이지</a>
<hr>
<!-- 2 자바스크립트로 이동 -->
<input type="button" value="두 번째 페이지" id="btn1">
<hr>
<!-- 3 폼을 통한 이동 -->
<form method="GET" action="ex19_scope_2.jsp">
<input type="hidden" name="a" value="<%= a %>">
<input type="submit" value="두 번째 페이지">
</form>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="http://pinnpublic.dothome.co.kr/cdn/example-min.js"></script>
<script>
$('#btn1').click(function() {
location.href = 'ex19_scope_2.jsp?a=<%= a %>';
});
</script>
</body>
</html>
첫 번째 페이지에서 데이터를 생성하면 두 번째 페이지에서 데이터를 사용할 수 있게 한다. 이러한 과정에서 데이터 전달 작업이 발생한다. 데이터를 전달할 수 있는 여러 가지 방법이 있다.
실패
클라이언트 코드로 페이지 이동하는 방식들은 변수 자체를 넘기는 게 아니라 다른 도구를 이용해 값만 넘기는 것이기 때문에 다른 페이지에서는 접근할 수 없는 방법이다. 즉, 이는 편법이다.
자바로 페이지를 이동하는 방식 또한 지역변수의 값을 복사한 것일 뿐, 전달한 것으로 착각하면 안 된다.
request 객체
//4. requesst 객체 >
request.setAttribute("d", 40);
//response.sendRedirect("ex19_scope_2.jsp");
pageContext.forward("ex19_scope_2.jsp?");
이동하는 방식을 sendRedirect에서 forward로 바꾸자 request 객체로 넘긴 데이터가 살아있는 것을 확인할 수 있다.
이는 한 페이지에서 사용한 값이 다른 페이지로 전송되었다는 의미이다.
이 방식은 단지 객체에 데이터를 넣고 페이지를 이동할 뿐인데, 명시적으로 데이터를 전송하고 수신하겠다는 액션 없이 데이터를 전달하기 때문에 단순하며 편리하다.
session, application 객체
//5. session 객체
session.setAttribute("e", 50);
//6. application 객체
application.setAttribute("f", 60);
response.sendRedirect("ex19_scope_2.jsp");
pageContext.forward("ex19_scope_2.jsp?");
session 객체와 application객체는 어떤 방식으로 보내든 데이터를 사용할 수 있다.
🍂내장 객체의 이동
사이트에 첫 사용자가 접속을 하면 application 객체가 만들어진다. 그와 동시에 첫 사용자에 대한 전용 객체인 session 객체가 만들어진다. 그리고 페이지를 실행하기 바로 직전에 pageContext 객체와 request 객체가 만들어진다.
이후에 페이지가 실행된다. 따라서 이 4개의 객체는 페이지가 실행되기도 전에 이미 존재하는 상태이다.
위 글에서 Round-Trip에 대해 설명할 때, sendRedirect 메서드는 페이지를 이동할 때, 페이지를 마치고 다시 클라이언트로 돌아간 다음에 사용자가 모르게 2번 페이지로 돌아간다고 했다. 반면에 forward 메서드는 바로 페이지를 이동한다.
sendRedirect 메서드로 페이지를 이동하여 클라이언트로 돌아갈 때 pageContext, request 객체는 죽지만, forward 메서드로 이동할 때 request 객체는 계속 살아 있다. request 객체는 forward 메서드로 읽으면 계속 살아있기 때문에 해당 데이터를 사용할 수 있는 것이다. 그리고 session과 application 객체는 페이지에 종속되지 않으므로 계속해서 살아있다.
클라이언트 이동은 페이지를 종료하고 나서 이동하는 방식이기 때문에 pageContext, request 객체는 무조건 죽어버린다. 때문에 request객체를 살리고 싶다면 forward 메서드를 사용해야 한다. 결론적으로 request 객체와 forward 메서드의 결합이 중요하다.
ex19_scope_2
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
String a = request.getParameter("a");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="http://pinnpublic.dothome.co.kr/cdn/example-min.css">
<style>
</style>
</head>
<body>
<h1>두 번째 페이지</h1>
<p>1. 지역 변수 a: <%= a %></p>
<%-- <p>2. 멤버 변수 b: <%= b %></p> --%>
<p>3. pageContext c: <%= pageContext.getAttribute("c") %></p>
<p>4. request d: <%= request.getAttribute("d") %></p>
<p>5. session e: <%= session.getAttribute("e") %></p>
<p>6. application f: <%= application.getAttribute("f") %></p>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="http://pinnpublic.dothome.co.kr/cdn/example-min.js"></script>
<script>
</script>
</body>
</html>