본문 바로가기
교육, 학습/멀티캠퍼스_풀 스택

Servlet - 쿠키(Cookie), 세션(HttpSession)

by 개발하는 경제학도 2022. 3. 15.

강의 소개

현재 수강하고 있는 멀티캠퍼스 k-digital 지능형 웹서비스 풀 스택 과정을 수강하며 적은 내용입니다.

교재로는 자바 웹을 다루는 기술을 사용하고 있습니다.


세션 트래킹

웹 페이지 연결 기능이다. 예를 들어 쇼핑몰에서 로그인한 뒤 장바구니에 가고, 게시판에 글을 쓸 수 있도록 로그인 상태를 유지하는 등이다.

HTTP 프로토콜은 각 웹 페이지의 상태나 정보를 다른 페이지들과 공유하지 않는 stateless 방식으로 통신을 한다. 따라서 웹 페이지나 서블릿끼리 상태나 정보를 공유하려면 웹 페이지 연결 기능인 세션 트래킹을 이용해야 한다.

 

종류

1. <hidden> 태그 : HTML의 <hidden> 태그를 이용한다

2. URL Rewriting: GET 방식으로 URL뒤에 정보를 붙여서 다른 페이지로 전송한다.

3. 쿠키: 클라이언트 PC의 Cookie 파일에 정보를 저장한 후 웹 페이지들이 공유한다.

4. 세션: 서버 메모리에 정보를 저장한 후 웹 페이지들이 공유한다.

 


 

쿠키

웹 페이지들 간 공유해야 하는 데이터를 클라이언트 PC에 저장해둔 후, 필요할 때 여러 웹 페이지들이 공유해서 사용할 수 있게 하는 방법이다.

 

특징

클라이언트 측 PC에 저장된다.(보안이 취약하다)

텍스트 파일 형태로 저장되어, 자바 객체를 생성한 뒤에 공유하는 것은 불가능하다.

브라우저가 제공하는 툴에서 정보 확인 가능하다.

기본적으로 정보 공유가 가능한 기간은 브라우저 닫을 때까지 이며, 공유 가능한 기간을 늘리는 것은 선택적이다. (ex. 1일, 30일, 365)

 

쿠키 API

javax.servlet.http.Cookie를 이용해서 쿠키 객체를 생성한다.

Cookie c = new Cookie("저장할 쿠키 이름", URLEncoder.encode("저장할 쿠키 값", "utf-8"));

HttpServletResponse의 addCookie 메서드를 이용해 클라이언트 브라우저에 쿠키를 전송한 후 저장한다.

response.addCookie(쿠키이름);

HttpServletRequest의 getCookie 메서드를 이용해 쿠키를 서버로 가져온다.

Cookies[] cookieArr = request.getCookies();

 

쿠키 종류

속성 Persistence 쿠키 Session 쿠키
생성 위치 클라이언트에 파일로 저장 브라우저 메모리에 생성
종료 시기 쿠키를 삭제, 쿠키의 설정 값이 종료된 경우 브라우저를 종료한 경우
최초 접속시 전송 여부 최초 접속 시 서버로 전송 최초 접속 시 서버로 전송 x
용도 로그인 유무, 팝업창 제한 사이트 접속시 Session 인증 정보 유지할 때
생성 방법 Cookie 클래스내 setMaxAge 메서드의 인자값으로
양수 지정
Cookie 클래스내 setMaxAge 메서드의 인자값으로
음수를 지정하거나, 해당 메서드를 사용하지 않고 쿠키 생성시

 

 

예시 코드

아래 예시는 사용자가 브라우저에서 로그인을 하면 클라이언트에서 쿠키를 만들어 서버로 전달하여 출력하는 코드이다.

예시에서 만들어진 쿠키는 클라이언트 측에 파일로 저장되는 persistence 쿠키이다. 

 

[클라이언트]

// 쿠키의 클라이언트측. : 쿠키 저장하는 역할 
@WebServlet("/cookieset")
public class CookieSetServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 사용자가 로그인했던 id를 파라미터로 입력받아서 쿠키로 저장.
		String id = request.getParameter("id");
        
        // 1. Cookie 객체를 생성한 후 c_id라는 이름으로 한글 정보를 인코딩해서 쿠키에 저장한다.
		Cookie id_cookie = new Cookie("c_id", id); 

		// 2. (옵션) 쿠키의 유효기간을 설정한다. 브라우저를 닫아도 설정 시간동안에는 쿠키가 살아있다.
		id_cookie.setMaxAge(60*60*24); 
		
		// 사용자의 로그인 시각을 쿠키로 저장 
		Date now = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		sdf.format(now);
		// IllegalArgumentException
		Cookie time_cookie = new Cookie("c_time", 
				java.net.URLEncoder.encode(sdf.format(now), "utf-8"));
		
		// 3. 생성된 쿠키를 브라우저로 전송한다.
		response.addCookie(id_cookie);
		response.addCookie(time_cookie);
		
		// 브라우저 출력
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		out.println("<h1>쿠키를 저장하였습니다.</h1>");
	}

}

 

[서버]

@WebServlet("/cookieget")
public class CookieGetServlet extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 출력 준비
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		
		// 1. request의 getCookies 메서드를 호출하여 브라우저에게 쿠키 정보를 요청한다.  
		// 쿠키는 여러개일 수 있어서, cookie 배열 리턴된다.
		Cookie[] c_array = request.getCookies();
		
        // 2. 쿠키 배열에 저장된 값들을 출력해본다.
        for(Cookie c : c_array) {
			out.println("쿠키이름 = " + c.getName());
			out.println("쿠키값 = " 
					+ java.net.URLDecoder.decode(c.getValue(), "utf-8"));
		}
	}

}

 

 

세션

웹 페이지들 간의 공유 정보를 서버에 저장해 두고 웹 페이지들을 매개해주는 방법이다.

 

특징

서버 측 메모리에 공유할 데이터를 저장해둔다.(보안에 민감한 데이터에 적절하다. ex. 로그인 정보)

세션은 각 브라우저 당 1개가 생성된다. (사용자당 1개)
세션의 정보 공유 기본기간은 브라우저 닫을 때까지이다.(
브라우저 닫지 않고 30분 동안 액션 없으면 세션은 자동 삭제된다.)
로그인 상태 유지나 쇼핑몰의 장바구니 담기 기능 등에 주로 활용된다.
자바 객체를 생성하여 공유할 수 있다.

 

세션 API (HttpSession 클래스)

서블릿에서 세션을 이용하기 위해 생성해야 하는 HttpSession 객체는 HttpServletRequest의 getSession메서드를 호출해서 생성한다. getSession메서드는 기존의 세션 객체가 존재하면 반환하고, 없으면 새로 생성한다.

HttpSession session = request.getSession();

setAttribute메서드를 이용해 세션 속성 이름이 name인 속성에 속성 값으로 value를 할당한다.

session.setAttribute(String name, Object value);

getAttribute메서드를 이용해 속성 이름이 name인 속성 값을 Object타입으로 반환한다.(해당되는 속성 이름이 없으면 null 값을 반환)

session.getAttribute(String name);

removeAttribute메서드를 이용해 세션 속성 이름이 name인 속성을 제거한다.

session.removeAttribute(String name);

invalidate메서드를 이용해 현재 생성된 세션을 소멸시킨다.

session.invalidate();

 

 

예시 코드

아래 코드는 로그인한 페이지에서 로그인 시 id, pw를 세션에 저장해두었다가 여러 서블릿(로그아웃 페이지, 마이페이지, 게시글 작성 페이지)과 공유하는 예제이다.

 

[LoginServlet]

@WebServlet(name = "a", urlPatterns = {"/loginsession"})
public class LoginServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// id, pw 입력받아 로그인정보 받아온다.
		String id = request.getParameter("id");
		String pw = request.getParameter("pw");
		
		// 1.요청된 브라우저의 세션 객체를 가져온다.(getSession메서드는 최초인지 아닌지에 따라서 2가지가 나뉨)
		HttpSession session = request.getSession();
		// 1번 상황: 최초로 브라우저 열고 현재파일 요청: 세션이 없다 -> 세션 객체 새로 생성 
		// 2번 상황: 브라우저 열어두고 다른 서블릿을 실행한 뒤 현재파일 요청 -> 세션이 이미 있는 상태. 이미 생성된 세션객체 가져온다.
		
		// 2. 요청 파라미터 id를 세션에 저장(세션은 서버측에만 저장) 
		session.setAttribute("session_id", id);
		
		// 브라우저 출력
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		if(id != null & pw != null) {
			out.println(id+"회원님 환영합니다.");
			out.println("<h1>사용 가능 메뉴는 다음과 같습니다.</h1>");
			out.println("<ul><li><a href = mypage > 내정보 확인하러 가기</a></li>");
			out.println("<li><a href = boardwriting > 글쓰러 가기</a></li>");
			out.println("<li><a href = logout > 로그아웃하러 가기</a></li></ul>"); // a태그로 이동시에는 세션을 통해서만 데이터 공유 가능. 반면 requestDispatcher의 forward, include는 이동과 데이터 전달 모두 가능.
		}
		else {
			out.println("로그인정보를 입력하세요.");
		}
	}

}

 

[LogoutServlet]

@WebServlet("/logout")
public class LogoutServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
	
		String printing = "";
		
		// 1. getSession: 최초 접근이면 세션을 생성 or 이미 존재하는 세션을 가져오거나
		HttpSession session = request.getSession();
		if(session.getAttribute("session_id") != null) { // 로그인되어있는 상황에서 로그아웃 
			printing = session.getAttribute("session_id") + "회원님";

			// 2. 로그아웃은 세션에 대한 정보를 삭제하면 된다. removeAttribute
			session.removeAttribute("session_id");
			
			printing += "로그아웃하셨습니다.";
		}
		else {
			printing = "<a href = loginsession>로그인 먼저 해주세요</a>";
		}
		
		// 출력 준비
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		out.println(printing);
	}

}

 

[MyPageServlet]

@WebServlet("/mypage")
public class MyPageServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		// 1. getSession: 최초 접근이면 세션을 생성 or 이미 존재하는 세션을 가져오거나
		HttpSession session = request.getSession();
		
		String session_id = "";
        // 2. getAttribute: 속성 이름에 해당되는 값을 Object타입으로 반환
		if(session.getAttribute("session_id") != null) {
			session_id = (String)session.getAttribute("session_id");
		}
		else {			
			session_id = "로그인 먼저";
		}
		
		// 브라우저 출력
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		out.println(session_id+"회원님 환영합니다.");
	}

}

 

[BoardWritingServlet]

@WebServlet("/boardwriting")
public class BoardWritingServlet extends HttpServlet {
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		// 1. getSession: 최초 접근이면 세션을 생성 or 이미 존재하는 세션을 가져오거나
		HttpSession session = request.getSession();
		
		// 요청 파라미터 id를 세션에 저장(세션은 서버측에만 저장)
		String session_id = (String)session.getAttribute("session_id");
		
		// 브라우저 출력
		response.setContentType("text/html;charset=utf-8");
		PrintWriter out = response.getWriter();
		
		if(session.getAttribute("session_id") != null) {
			out.println("<h1>" + session_id + "회원님, 글쓰기 가능합니다.</h1>");
			
			out.println("<table><th>글쓰기 폼</th>"
					+ "<tr><td>제목</td><td><input type = text placeholder = 제목작성 name = 'title'></td></tr>"
					+ "<tr><td>내용</td><td><textarea name ='contents' rows = 5 cols = 50>글작성</textarea></td></tr>"
					+ "<tr><td>작성자</td><td><input type = text name = 'writer' value="+session_id+"></td></tr>"
					+ "</table>");
		}
		
	}

}

 

댓글