본문 바로가기
JSP/성낙현의 JSP 자바 웹 프로그래밍

세션(Session)

by k-mozzi 2023. 6. 8.
반응형
Preface

 

이번 장에선 JSP와 OracleDB를 사용해 간단한 로그인 폼을 만들었다.

 

지난번 Python과 php, MySQL을 이용해 게시판을 제작했을 땐 솔직히 php 코드를 이해하지 못한 체 다른 블로그에 있는 코드를 복사해서 사용했을 뿐이었다.

 

그러나 DB의 연동부터 서버 사이드 스크립트 언어인 JSP의 코드까지 모두 직접 작성하며 제작을 하다보니 작동 방식과 연결 방식을 쉽게 이해할 수 있었다.

 

물론 이해만 했을 뿐이지, 혼자 힘으로 모든 코드를 작성할 수 있으려면 작성해둔 코드를 여러 번 읽어보며 복습하는 시간이 꼭 필요할 것 같다.


 

1. 세션이란?

 

 

- 세션(Session): 클라이언트가 웹 브라우저를 통해 서버에 접속한 후 용무를 처리하고 웹 브라우저를 닫아 서버와의 접속을 종료하는 하나의 단위

→ 클라이언트가 서버에 접속해 있는 동안 상태를 유지하는 것이 목적이다.

 


 

2. 세션 설정, 확인, 삭제

 

 

- 세션의 특징

1) 세션은 웹 브라우저를 실행할 때마다 새롭게 생성된다.

2) 세션은 설정된 유지 시간동안 유지된다.

→ 유지 시간이 만료되기 전에 새로운 요청이 들어오면 수명이 연장된다.

 

 

- 세션의 유지 시간을 설정하는 방법

1) web.xml에서 설정

→ web.xml에선 유지 시간을 분 단위로 설정한다.

<session-config>
	<session-timeout>20</session-timeout>
</session-config>

2) JSP 파일에서 session 내장 객체가 제공하는 메서드를 사용

→ 해당 메서드의 시간 단위는 초이다.

<%
session.setMaxInactiveInterval(1800);
%>

 

 

- 세션의 속성

1) 유지 시간

2) 아이디: 웹 브라우저를 새롭게 열 때마다 다른 값으로 설정된다.

3) 최초 요청 시각

4) 최종 요청 시각

<%@ page import="java.util.Date"%>
<%@ page import="java.text.SimpleDateFormat"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

long creationTime = session.getCreationTime();
String creationTimeStr = dateFormat.format(new Date(creationTime));

long lastTime = session.getLastAccessedTime();
String lastTimeStr = dateFormat.format(new Date(lastTime));
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Session</title>
</head>
<body>
	<h2>Session 설정 확인</h2>
	<ul>
		<li>세션 유지 시간: <%=session.getMaxInactiveInterval()%></li>
		<li>세션 아이디: <%=session.getId()%></li>
		<li>최초 요청 시각: <%=creationTimeStr%></li>
		<li>마지막 요청 시각: <%=lastTimeStr%></li>
	</ul>
</body>
</html>

 

 

- JSESSIONID: 요청을 보낸 웹 브라우저가 현재 연결되어 있는지 확인하는 데 사용한다.

→ 즉, 웹 브라우저로부터 전달받은 JSESSIONID를 통해 서버는 동일한 세션인지 확인할 수 있다.

 


 

3. 세션과 DB를 이용한 로그인 구현

 

 

- 로그인 폼

1) validateForm( ): JS로 작성한 유효성 검사 함수로, ID와 PW 중 빈 값이 있다면 경고창을 띄운다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Session</title>
</head>
<body>
	<jsp:include page="../Common/Link.jsp" />
	<h2>로그인 페이지</h2>
	<span style="color: red; font-size: 1.2em;">
	<%=request.getAttribute("LoginErrMsg") == null ? "" : request.getAttribute("LoginErrMsg")%>
	</span>
	<%
	if (session.getAttribute("UserId") == null) {	// 로그아웃 상태
	%>
	<script>
		function validateForm(form) {
			if (!form.user_id.value) {
				alert("아이디를 입력하세요.");
				return false;
			}
			if (form.user_pw.value == "") {
				alert("패스워드를 입력하세요.");
				return false;
			}
		}
	</script>
	<form action="LoginProcess.jsp" method="post" name="loginFrm"
		onsubmit="return validateForm(this);">
		아이디: <input type="text" name="user_id" /><br /> 패스워드: <input
			type="password" name="user_pw" /><br /> <input type="submit"
			value="로그인하기" />
	</form>
	<%
	} else {	//로그인 상태
	%>
	<%=session.getAttribute("UserName")%>
	회원님, 로그인하셨습니다.
	<br />
	<a href="Logout.jsp">[로그아웃]</a>
	<%
	}
	%>
</body>
</html>

 

 

- DTO(Data Transfer Object): 계층 사이에서 데이터를 교환하기 위해 생성하는 객체

→ DTO 클래스는 일반적으로 테이블당 하나씩 생성하며, 테이블의 컬럼과 동일한 멤버 변수를 갖는다.

package membership;

public class MemberDTO {

	private String id;
	private String pass;
	private String name;
	private String regidate;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getPass() {
		return pass;
	}

	public void setPass(String pass) {
		this.pass = pass;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getRegidate() {
		return regidate;
	}

	public void setRegidate(String regidate) {
		this.regidate = regidate;
	}

}

 

 

- DAO(Data Access Object): DB의 데이터에 접근하기 위한 객체

1) 보통 JDBC를 통해 구현하며, 하나의 테이블에서 수행할 수 있는 CRUD를 전담한다.

2) CRUD에 해당하는 쿼리문을 실행한 후, 얻어온 결과를 DTO 객체에 담아 반환한다.

package membership;

import common.JDBConnect;

public class MemberDAO extends JDBConnect {

	// 명시한 DB로의 연결이 완료된 MemberDAO 객체를 생성합니다.
	public MemberDAO(String driver, String url, String id, String pw) {
		super(driver, url, id, pw);
	}

	// 명시한 아이디/패스워드와 일치하는 회원 정보를 반환합니다.
	public MemberDTO getMemberDTO(String uid, String upass) {
		MemberDTO dto = new MemberDTO();
		String query = "SELECT * FROM member WHERE id=? AND pass=?";

		try {
			psmt = con.prepareStatement(query);
			psmt.setString(1, uid);
			psmt.setString(2, upass);
			rs = psmt.executeQuery();

			if (rs.next()) {
				dto.setId(rs.getString("id"));
				dto.setPass(rs.getString("pass"));
				dto.setName(rs.getString(3));
				dto.setRegidate(rs.getString(4));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return dto;
	}

}

→ 상속한 Java 클래스

package common;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import javax.servlet.ServletContext;

public class JDBConnect {
	public Connection con;
	public Statement stmt;
	public PreparedStatement psmt;
	public ResultSet rs;

	public JDBConnect() {
		try {
			Class.forName("oracle.jdbc.OracleDriver");

			String url = "jdbc:oracle:thin:@localhost:1521:xe";
			String id = "musthave";
			String pwd = "1234";
			con = DriverManager.getConnection(url, id, pwd);

			System.out.println("DB 연결 성공(기본 생성자)");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public JDBConnect(String driver, String url, String id, String pwd) {
		try {
			Class.forName(driver);

			con = DriverManager.getConnection(url, id, pwd);

			System.out.println("DB 연결 성공(인수 생성자 1)");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public JDBConnect(ServletContext application) {
		try {
			String driver = application.getInitParameter("OracleDriver");
			Class.forName(driver);

			String url = application.getInitParameter("OracleURL");
			String id = application.getInitParameter("OracleId");
			String pwd = application.getInitParameter("OraclePwd");
			con = DriverManager.getConnection(url, id, pwd);

			System.out.println("DB 연결 성공(인수 생성자 2)");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void close() {
		try {
			if (rs != null)
				rs.close();
			if (stmt != null)
				stmt.close();
			if (psmt != null)
				psmt.close();
			if (con != null)
				con.close();

			System.out.println("JDBC 자원 해제");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

 

- 로그인 처리

<%@ page import="membership.*"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%
String userId = request.getParameter("user_id");
String userPwd = request.getParameter("user_pw");

String oracleDriver = application.getInitParameter("OracleDriver");
String oracleURL = application.getInitParameter("OracleURL");
String oracleId = application.getInitParameter("OracleId");
String oraclePwd = application.getInitParameter("OraclePwd");

MemberDAO dao = new MemberDAO(oracleDriver, oracleURL, oracleId, oraclePwd);
MemberDTO memberDTO = dao.getMemberDTO(userId, userPwd);
dao.close();

if (memberDTO.getId() != null) {
	session.setAttribute("UserId", memberDTO.getId());
	session.setAttribute("UserName", memberDTO.getName());
	response.sendRedirect("LoginForm.jsp");
} else {
	request.setAttribute("LoginErrMsg", "로그인 오류입니다.");
	request.getRequestDispatcher("LoginForm.jsp").forward(request, response);
}
%>

 

 

- 로그아웃 처리

1) removeAttribute( ): 인수로 지정한 속성을 삭제한다.

2) invalidate( ): 세션 자체를 무효화한다.

→ session 영역의 모든 속성을 한번에 삭제하므로, 로그아웃 시에는 해당 메서드를 사용하는 것이 좋다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%
//방법 1: 회원인증정보 속성 삭제
/* session.removeAttribute("UserId");
session.removeAttribute("UserName"); */

//방법 2: 모든 속성 한번에 삭제
session.invalidate();

//속성 삭제 후 페이지 이동
response.sendRedirect("LoginForm.jsp");
%>

 

 

- 앞으로 사용할 공통 링크

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<table border="1" width="90%">
	<tr>
		<td align="center">
		<% if(session.getAttribute("UserId") == null){ %>
			<a href="../ch6/LoginForm.jsp">로그인</a>
		<% } else { %>
			<a href="../ch6/Logout.jsp">로그아웃</a>
		<% } %>
			&nbsp;&nbsp;&nbsp;	<!-- 메뉴 사이의 공백 확보용 특수 문자 -->
			<a href="../ch8/List.jsp">게시판(페이징X)</a>
			&nbsp;&nbsp;&nbsp;
			<a href="../ch9/List.jsp">게시판(페이징O)</a>
		</td>
	</tr>
</table>

 


 

4. 쿠키 vs 세션

 

 

- 로그인은 쿠키보다는 세션을 이용해 구현하는 것이 좋다.

 

 

- 쿠키와 세션의 차이

  쿠키 세션
저장 위치 / 형식 클라이언트 PC에 text로 저장된다. 웹 서버에 Object 타입으로 저장된다.
보안 클라이언트에 저장되므로 보안에 취약하다. 서버에 저장되므로 보안에 안전하다.
자원 / 속도 서버 자원을 사용하지 않으므로 세션보다 빠르다. 서버 자원을 사용하므로 쿠키보다 느리다.
용량 용량의 제한이 있다. 서버가 허용하는 한 제한이 없다.
유지 시간 쿠키 생성 시 설정한다.
→ 설정된 시간이 경과되면 무조건 삭제된다.
서버의 web.xml에서 설정한다.
→ 설정된 시간 내라도 동작이 있다면 삭제되지 않고 유지된다.

 

728x90
반응형

댓글