[ 세션 관리 ]
HTTP의 특성 ⇒ Stateless (상태 정보를 유지하지 않는다)
: 클라이언트와 서버가 서로 통신할 때, request ↔ response가 한 번 이루어지면, 클라이언트에 대한 정보를 유지하지 않는다.
(한 번의 통신 후에는 클라이언트와 서버의 관계가 끊어진다!)
(불필요하게 클라이언트의 정보를 서버가 유지하게 되면, 서버가 무거워지기 때문에!)
⇒ 세션 관리의 목적 : 사용자 정보를 일정 조건 동안 유지하기 위해!
: 사용자의 상태 정보의 유지가 필요할 때가 있다.
예를 들어 로그인 정보를 미리 저장해놔야, 메일을 확인하고, 검색하고 좋아요를 누르는 작업마다( request ↔ response ),
새로 로그인을 해야하는 번거로움이 발생하기 때문에, 이를 해결하기 위해서, 쿠키와 세션으로 관리한다!
그 외에도, 7일간 보지 않기 팝업창, 쇼핑몰 장바구니 기능 등에서도 활용되고 있다.
[ Cookie 쿠키 ]
: 클라이언트(브라우저) 측에 사용자 상태 정보를 저장한다.
> 쿠키를 발급받고 사용하는 과정
- 저장 용량 및 데이터 타입에 제한이 있다.
- 저장 용량 : 4KB
- 데이터 타입 : 문자열 (String) - 데이터 타입은 문자열로 한정된다.
- 쿠키 정보를 서버에서 response시에 클라이언트로 전송하고,
cookie정보를 확인할 때는 request를 이용해서 서버에서 확인한다. - > 쿠키 만들기
: server에서 client에게 response 할 때, 클라이언트에 cookie가 저장이 된다. ( 쿠키를 심는다.)
→ response.addCookie(cookie);
> 쿠키 읽기
: 그 다음 단계에서 client가 request할 때, cookie가 server로 넘어오게 된다. ( 쿠키를 확인한다.)
→ request.getCookies(); - 일반적으로 cookie는 유효시간을 설정한다.
설정된 유효시간이 지나면 메모리에서 해제된다 (사용불가)
만약, 유효시간을 설정하지 않으면, 브라우저가 실행될 때만 정보가 유지된다.
Cookie 예제
쿠키를 할당하는 역할
/setCookieServlet.java
package step1;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 쿠키를 할당하는 역할
*/
@WebServlet("/SetCookieServlet")
public class SetCookieServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<h3>");
out.println(getServletName()+"에서 쿠키를 클라이언트에게 전달<br>");
// 현재 시간 출력
//공란 -> 하이픈으로 변경
Date time = new Date();
String timeString = time.toString().replace(" ", "-");
out.println(timeString);
//javax.servlet.http.Cookie
//new Cookie(name, value) - 찾을 때 name으로 찾기
Cookie cookie = new Cookie("time", timeString);
//유효 시간 5초로 설정
cookie.setMaxAge(5);
//client에게 cookie를 전송
response.addCookie(cookie);
//링크 생성
out.println("<br><br><a href=getCookieServlet>step2.getCookieServlet에서 쿠키 정보 확인</a>");
out.println("</h3>");
out.close();
}
}
할당된 쿠키를 확인하는 역할
/getCookieServlet.java
package step2;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* 할당된 쿠키를 확인하는 역할
*/
@WebServlet("/getCookieServlet")
public class getCookieServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<h4>");
out.println(getServletName()+"에서 클라이언트로부터 time 쿠키 정보 확인<br><br>");
//client에 저장된 name=time 쿠키 정보를 반환받아 본다
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (int i = 0; i < cookies.length; i++) {
if (cookies[i].getName().contentEquals("time")) {
out.println(cookies[i].getValue());
}
}
} else {
out.println("쿠키 정보가 없습니다.");
}
out.println("</h4>");
out.close();
}
}
결과 : 5초 지난 후 쿠키 정보가 삭제된다.
[ 위 예제의 진행 과정(흐름) ]
WAS (Web Container)
client(browser) ---> request -----> SetCookieServlet
Cookie 생성
cookie.setMaxAge(30) : 유효시간 설정
response.addCookie(cookie) : 클라이언트에 저장할 쿠키를 추가
<-- response -- reponse : 즉, 응답 시에 클라이언트에게 쿠키 전달 (쿠키 심기)
cookie가 저장
client(browser) ---> request -----> GetCookieServlet
request.getCookies() 를 이용해 Cookie 배열을 반환
쿠키가 존재하면
-> name에 따른 value를 화면에 출력
쿠키가 존재하지 않으면
-> (쿠키 유효시간이 만료)
-> '쿠키가 없습니다' 라는 메세지를 화면에 출력
[ Session 세션 ]
: 서버 측에 사용자 상태 정보를 저장
- 저장하는 데이터의 용량 및 타입에 제한이 없다.
- WAS에 세션 유지 기간이 별도로 설정되어 있다.
(* 참고 - Tomcat은 30분으로 설정되어 있다.) - tomcat\conf\web.xml에 아래와 같은 코드가 있다.
: 지정한 유효시간(30분) 내에 새로운 요청이 없을 때, 세션이 만료된다.
<session-config>
<session-timeout>30</session-timeout>
</session-config>
: 만약 웹어플리케이션 별로 세션 유효시간을 별도로 설정하고자 한다면,
웹 어플리케이션의 DD(Deployment Descriptor - 배포 기술서)인 web.xml에 아래와 같이 설정하면 된다.
(아래와 같이 설정하면 1분간 세션이 유효하다)
<session-config>
<session-timeout>1</session-timeout>
</session-config>
HttpSession 관련 주요 API
참고 링크 : https://javaee.github.io/javaee-spec/javadocs/
- [HttpServletRequest의 session 주요 메서드]
- request.getSession( ) : HttpSession
→ 세션이 없으면 새로 생성해주고, 있으면 기존 세션을 반환해준다. - request.getSession( true ) : HttpSession
→ 위와 동일 - request.getSession( false ) : HttpSession
→ 세션이 없으면 null을 반환해주고, 있으면 기존 세션을 반환해준다. - [ HttpSession의 주요 메서드 ]
- HttpSession session = request.getSession();
- session.setAttribute(name, value)
→ 세션에 있는 특정 정보를 공유 - session.getAttribute(name) : Object
→ 세션에 있는 특정 정보를 반환 - session.removeAttribute(name) : boolean
→ 세션에 있는 특정 정보를 삭제 - session.invalidate()
→ 세션은 무효화 (로그아웃 시에 사용)
Session 예제
SessionOne : 세션 생성 & 세션에 정보 할당
SessionTwo: 세션 유무 확인 & 기존 세션 정보 반환
SessionThree: 세션 유무 확인 후, 있으면 세션 무효화
SessionOne에는 request.getSession(true)를, SessionTwo에는 request.getSession(false)를 적용한다.
SessionTwo에서 false로 기입해주는 이유는, 기존에 세션이 있는지 확인하기 위함이다.
(세션이 없으면 세션을 새로 만드는 것이 아니라, null이 반환되어야, 기존 세션 유무를 확인할 수 있기 때문에!)
또한 SessionOne에서 session.setAttribute(name, value)로 해당 세션에 정보를 할당한다.SessionTwo에서 session.getAtrribute(name)를 통해 해당 세션의 정보를 반환받는다.
SessionThree에서는 기존 세션이 있는지 확인해서 ( request.getSession(false) ),
있으면 세션을 무효시킨다 (session.invalidate() ). (⇒ 로그아웃 기능)
/SessionOne.java
package step3;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Session One Servlet
*/
@WebServlet("/SessionOne")
public class SessionOne extends HttpServlet {
private static final long serialVersionUID = 1L;
//doGet() method
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<h3>" + getServletName() + "<br><br>");
/*request.getSession() method
*: 기존 세션이 없으면 새로 세션을 생성,
* 만약 기존 세션이 있으면 기존 세션을 반환
*/
HttpSession session = request.getSession();
// 세션 객체에 정보를 할당
session.setAttribute("nick", "파프리카");
session.setAttribute("time", new Date());
//session.getId() : 내부적으로 이 세션 아이디가 client에 쿠키로 저장됨
System.out.println(session.getId());
out.println("세션 아이디: " + session.getId() + "<br>");
//다른 Session으로 이동 링크
out.println("<br><a href = SessionTwo>SessionTwo으로 이동</a>");
out.println("</h3>");
out.close();
}
}
/SessionTwo.java
package step4;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Session Two Servlet
*/
@WebServlet("/SessionTwo")
public class SessionTwo extends HttpServlet {
private static final long serialVersionUID = 1L;
// doGet() method
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<h3>" + getServletName() + "<br><br>");
/*request.getSession(false) method
*: 기존 세션이 없으면 null 반환,
* 만약 기존 세션이 있으면 기존 세션을 반환
*/
HttpSession session = request.getSession(false);
if(session == null){
out.println("세션이 없습니다!<br>");
} else {
out.println("세션 아이디: " + session.getId() + "<br>");
// 기존 세션에 있던 정보 반환받기
String nick = (String) session.getAttribute("nick");
Date time = (Date) session.getAttribute("time");
out.println("nick 반환 : " + nick + "<br>");
out.println("time 반환 : " + time + "<br>");
}
//다른 Session으로 이동 링크
out.println("<br><a href = SessionOne>SessionOne으로 이동</a>");
out.println("<br><a href = SessionThree>SessionThree으로 이동</a>");
out.println("</h3>");
out.close();
}
}
/SessionThree.java
package step5;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* Session Three Servlet
*/
@WebServlet("/SessionThree")
public class SessionThree extends HttpServlet {
private static final long serialVersionUID = 1L;
// doGet() method
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html; charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<h3>" + getServletName() + "<br><br>");
/*
* 기존 세션이 있는지 확인해서, 있으면 세션을 무효시킨다.
* (로그아웃 기능)
* requeset.getSession(false) : 기존 세션이 있으면 반환하고, 아니면 null반환
*/
HttpSession session = request.getSession(false);
if (session != null) { //세션이 있으면
session.invalidate(); //무효화 시킴
out.println("기존 세션을 무효화시킴.. 로그아웃");
} else {
out.println("세션이 없습니다!");
}
//다른 Session으로 이동 링크
out.println("<br><br><a href = SessionTwo>SessionTwo에서 확인</a>");
out.println("<br><a href = SessionOne>SessionOne에서 확인</a>");
out.println("</h3>");
out.close();
}
}
[ 결과 ]
SessionTwo에서 시작한다.
(세션이 없는 상태에서 시작하고, SessionOne에서 세션을 만든 후 과정으로 진행하기 위해서)