
JSP 1차 시험진행(chap01 기본개요와 구조 ~ chap05 데이터베이스)
선생님 TIP
이클리스 JUnit 테스트 해보기
JUnit 라이브러리 생성
경로 : 프로젝트 폴더 우 클릭 > Properties > Java Build Path > Libraries
① 위 경로 접속 후 [Add library...] 클릭
② 리스트에서 JUnit 클릭
③ JUnit5 선택 후 [Finish] 클릭
④ JUnit 라이브러리 생성 후 프로퍼티 설정 창에 서 [Apply and Close] 클릭 하여 저장

JUnit 클래스 작성
경로 : 프로젝트 루트 > src > Java > Common > test > JDBConnectTest.java
① JUnit 클래스를 생성할 폴더에 우클릭 - [NEW] - [Other] 또는 Ctrl + N 해서 Java > JUnit > JUnit Test Case 선택 후 [Next]
② New JUnit Jupiter test / 파일명은, JDBConnecTest 로 설정 선택 후 [Next]
③ JDBConnect 부분 전체 선택 후 [Next]
④ 설정한 내용 대로 Java 파일 만들어짐
⑤ Assert.assertNotNull(jdbc); 메서드를 이용해 JDBC 객체의 null이 아닌게 맞는 지 확인
⑥ Run 아이콘 > Run AS > JUnit Test 선택 후 실행

package common.test;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import common.JDBConnect;
class JDBConnectTest {
@Test
void testJDBConnect() {
//fail("Not yet implemented");
JDBConnect jdbc = new JDBConnect();
// 성공조건 : null이 아니면...
Assert.assertNotNull(jdbc);
}
@Test
void testJDBConnectStringStringStringString() {
fail("Not yet implemented");
}
@Test
void testJDBConnectServletContext() {
fail("Not yet implemented");
}
@Test
void testClose() {
fail("Not yet implemented");
}
}
Dynamic Web Project 생성 시 생성관리자 경로 설명

① Java 파일이 저장되는 경로
② Java 파일이 class 파일로 컴파일되는 경로
③ 프로젝트 루트 경로
④ 웹 애플리케이션의 루트 경로
DTO vs VO
package member;
import java.time.LocalDateTime;
public class MemberDTO {
// DTO = Data Transfer Object 데이터 전송용 객체 => 데이터를 갖고와서 필요에 따라 연산 및 조작을 하는 객체
// VO = V
// 많은 책에서는 DTO와 VO를 같은 개념으로 보지만, 근본적으로는 다른 개념
private String memberId;
private String name;
private String pwd;
private String jumin;
private String addr1;
private String addr2;
private String addr;
private String birthday;
private String jobCode;
private long mileage;
private String memberState;
private LocalDateTime regDate;
private LocalDateTime leaveDate;
private LocalDateTime pwd_change_date;
public void setAddr() {
this.addr = this.addr1 + this.addr2;
}
public String getAddr() {
return this.addr;
}
}
class MemberVO {
private String memberId;
private String name;
private String pwd;
private String jumin;
private String addr1;
private String addr2;
private String birthday;
private String jobCode;
private long mileage;
private String memberState;
private LocalDateTime regDate;
private LocalDateTime leaveDate;
private LocalDateTime pwd_change_date;
public String getMemberId() {
return memberId;
}
public void setMemberId(String memberId) {
this.memberId = memberId;
}
public String getName() {
return name;
}
... 생략...
}
성낙현의 JSP 자바 웹 프로그래밍
chap 5 : JDBC 이용해서 Select문 날려보기
<%@page import="java.util.Date"%>
<%@page import="java.time.LocalDateTime"%>
<%@page import="java.sql.ResultSet"%>
<%@page import="java.sql.Statement"%>
<%@page import="common.JDBConnect"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 목록 조회</title>
</head>
<body>
<%
// DB 연결
JDBConnect jdbc = new JDBConnect();
// 쿼리문 String으로 작성
String sql = "SELECT memberId, name, pwd, jumin, addr1, addr2, birthday, jobCode, mileage, memberState, regDate, leaveDate, pwd_change_date FROM tbl_member";
// Statement 생성
Statement stmt = jdbc.conn.createStatement();
// Statement 를 exequteQuery(SELECT문 용)로 실행
ResultSet rs = stmt.executeQuery(sql);
// 출력하기
while(rs.next()) {
// ResultSet은 행 별로 갖고오는 방식임. next() 메서드는 다음 갖고올 행이 있는지 여부를 boolean 값으로 반환하는 함수
String member_id = rs.getString(1);
// SELECT문에 입력한 컬럼 순서를 숫자로 입력해도 되고 직접 컬럼명을 String으로 입력해도됨.
String name = rs.getString(2);
String pwd = rs.getString(3);
String jumin = rs.getString("jumin");
Date reg_date = rs.getDate("regDate");
out.println(String.format("%s, %s, %s, $s, %s", member_id, name, pwd, jumin));
}
%>
</body>
</html>
chap06 : 세션
[이론]
- 세션 : 웹 브라우저를 통해 서버에 접속하여 작업 후
웹 브라우저를 닫아서 서버와의 접속을 종료하는 단위를 "세션" 이라고 합니다.
- 세션의 주요 메서드
● 세션 속성 추가 : void setAttribute(String name, Object value)
세션에 속성을 추가하는 메소드
● 세션 속성 가져오기 : Object getAttribute(String name)
세션에 저장된 속성 중 입력된 name의 값을 가져옵니다.
가져온 값의 경우 Object 타입이기 때문에 알맞은 타입으로 캐스팅이 필요합니다.
● 세션 속성 삭제하기
1) void removeAttribute(String name)
세션에 저장된 속성 중 입력된 name의 속성을 삭제합니다.
2) void invalidate()
세션 자체를 무효화하는 메서드로, 무효화하면서 저장된 속성도 전부 삭제됩니다.
● 유지 시간(수명) 설정 : void setMaxInactiveInterval(int seconds)
세션은 설정된 유지시간 동안 유지되며, 유지 시간이 만료되기 전에 새로운 요청이 들어오면
설정된 유지시간이 다시 채워지며 수명이 계속 연장 됩니다.
세션은 설정된 유지시간 동안 아무런 요청이 없어서 그대로 만료되거나(세션 타임아웃),
웹 브라우저를 닫으면 만료됩니다.
1) 프로젝트의 WEB-INF > web.xml에서 설정
<session-config>
<session-timeout>20</session-timeout>
</session-config>
=> 분 단위로 설정
2) setMaxInactiveInterval()을 이용해서 설정
session.setMaxInactiveInterval(1200);
=> 초 단위로 설정
● 유지 시간(수명) 가져오기 : int getMaxInactiveInterval()
현재 세션에 설정되어 있는 수명을 리턴해줍니다.
● 세션의 최초 요청 시간 가져오기 : long getCreationTime()
타임스탬프 형식으로 가져옵니다.
● 세션의 마지막 요청 시간 가져오기 : long getLastAccessedTime()
타임스탬프 형식으로 가져옵니다.
● 웹 브라우저 생성한 세션 아이디 가져오기 : String getId()
- JSESSIONID
쿠키를 조회하다 보면 스스로 설정한 적 없는 JSESSIONID가 조회되는데
이는 톰캣 컨테이너에서 자동으로 생성해주는 부분으로,
서버에 저장된 세션의 아이디를 쿠키로 저장하여 클라이언트 측에 저장해놓은 세션 아이디 입니다.
해당 세션 아이디가 담긴 쿠키를 통해 서버는 해당 클라이언트의 세션 정보가 어떤것인지
아래의 과정을 통해 확인할 수 있습니다.
1. 웹 브라우저가 웹 서비스에 최초 접속 시 컨테이너는 세션을 새로 생성하여
세션아이디를 쿠키로 저장하고 응답헤더에 담아 클라이언트에 보냅니다.
2. 클라이언트는 쿠키에 담긴 세션 아이디를 요청 시 마다 서버에 보냅니다.
3. 서버는 클라이언트가 보낸 세션 아이디가 담긴 쿠키를 통해
해당 클라이언트의 기존 세션을 찾고 수명을 연장합니다.
=> 클라이언트 측에서 모든 쿠키를 냅다 지워버리면,
세션아이디가 담긴 쿠키도 없어져서 기존 세션과 연결할 정보가 없어집니다.
- 쿠키 vs 세션
| 쿠키 | 세션
-----------------------------------------------------------------------------------
1. 저장위치 | 클라이언트 pc에 text로 저장 | 웹 서버에 속성 값이 Object 타입으로 저장
2. 보안 | 클라이언트에 저장되어 보안취약 | 서버에 저장되어 보안 비교적 안전
| 사용자 스스로 변조가 가능하고 |
| 사용자가 쿠키를 거부할 수 있음 |
3. 속도 | 세션보다 빠름 | 서버자원을 사용하여 쿠키보다 느림
4. 용량 | 용량의 제한이 있음 | 서버가 허용하는한 별다른 제한 없음
| 최대 3000개 / 1개당 4096byte|
| 한 웹애플리케이션 당 50개 |
5. 유지시간 | 쿠키 생성 시 수명이 설정되며 | 서버의 web.xml에서 설정
| 설정된 시간이 지나면 무조건 삭제| 설정된 시간 내 동작이 있을 경우 계속 연장
로그인 페이지 구현 실습
<!-- login.jsp -->
<%@page import="java.util.Date"%>
<%@page import="java.text.SimpleDateFormat"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>세션 객체</title>
</head>
<body>
<%
SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
// 시간 출력하기 위해 변환화는 과정
long createTime = session.getCreationTime();
String strCreateTime = dateFormat.format(new Date(createTime));
long lastAccTime = session.getLastAccessedTime();
String strLastAccTime = dateFormat.format(new Date(lastAccTime));
%>
<%
String id = "";
if (session.getAttribute("UserId") != null) {
id = (String) session.getAttribute("UserId");
}
String name = "";
if (session.getAttribute("UserName") != null) {
name = (String) session.getAttribute("UserName");
}
String errMsg ="";
if (request.getAttribute("errMsg") != null) {
errMsg = (String) request.getAttribute("errMsg");
}
%>
<h2>세션 정보</h2>
세션 유지 시간 : <%= session.getMaxInactiveInterval() %> <br>
세션 아이디 : <%= session.getId() %> <br>
세션 최초 요청 시간 : <%= strCreateTime %> <br>
세션 마지막 요청 시간 : <%= strLastAccTime %> <br>
세션 사용자 ID : <%= id %> <br>
세션 사용자 이름 : <%= name %> <br>
<h2>로그인</h2>
<% %>
<span style="color : red; font-size 20px">
<%= errMsg %>
</span>
<form name="frmLogin" id="frmLogin" action="login_ok.jsp" method="post"> <br>
아이디 : <input type="text" name="id" id="id" value="" maxlength="20"> <br>
비밀번호 : <input type="password" name="pwd" id="pwd" value="" maxlength="20">
<input type="submit" value="로그인">
<br>
<input type="submit" value="로그아웃">
</form>
<div>
<%
if(id != "") {
out.print("<h2>회원정보</h2>" + "id : " + id + "<br>" + "name : " + name);
}
%>
</div>
<script>
const logout = document.querySelector("input[value = '로그아웃']");
const frm = document.querySelector("#frmLogin");
logout.addEventListener("click", (e)=> {
e.preventDefault();
frm.action = "logout.jsp";
frm.submit();
})
</script>
</body>
</html>
<!-- login_ok.jsp -->
<%@page import="member.MemberDTO"%>
<%@ page import="member.MemberDAO"%>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<%
String id = request.getParameter("id");
String pwd = request.getParameter("pwd");
out.println(String.format("아이디 : %s, 비밀번호 : %s <br>", id, pwd));
// DB 회원정보 갖고와서 써먹어보기
String driver = application.getInitParameter("Driver");
String url = application.getInitParameter("URL");
String dbId = application.getInitParameter("dbId");
String dbPwd = application.getInitParameter("dbPwd");
MemberDAO dao = new MemberDAO(driver, url, dbId, dbPwd);
MemberDTO dto = dao.getMemberInfo(id, pwd);
dao.close();
if(dto != null && dto.getMemberId() != null) {
session.setAttribute("UserId", dto.getMemberId());
session.setAttribute("UserName", dto.getName());
out.print(dto.getMemberId());
response.sendRedirect("login.jsp");
} else {
out.print(dto.getMemberId());
request.setAttribute("errMsg", "로그인 오류");
request.getRequestDispatcher("login.jsp").forward(request, response);
// response.sendRedirect() 해버리면, request 요청이 종결되서 위 속성 저장한거 없어짐 따라서 request.getRequestDispatcher()로 담아서 이동
}
%>
<!-- logout.jsp -->
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page trimDirectiveWhitespaces="true" %>
<%
//로그아웃
// 세션 속성 지워버리기
//session.removeAttribute("UserId");
//session.removeAttribute("UserName");
session.invalidate();
/// 기존에는 속성 하나하나 지우는 걸로 하였으나 invalidate()로 세션을 무효화 해버리면, 세션정보를 아예 끊어버려서 더 효율적이라고 해서 바꿈
// 다시 로그인 페이지로 리다이렉트
response.sendRedirect("login.jsp");
%>