CREATE TABLE todo(
id number primary key,
todo varchar2(150) not null,
created date default sysdate not null,
completed number(1) default 0 not null -- 할 일 수행 여부, 0이면 미완료, 1이면 완료
);
create sequence todo_seq;
<%@ page language="java" contentType="text/plain; charset=UTF-8"
pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@ page import="kr.util.DBUtil"%>
<%@ page import="java.sql.Connection"%>
<%@ page import="java.sql.PreparedStatement"%>
<%
request.setCharacterEncoding("utf-8");
String todo = request.getParameter("todo");
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try{
conn = DBUtil.getConnection();
sql = "INSERT INTO todo(id,todo) VALUES(todo_seq.nextval,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, todo);
pstmt.executeUpdate();
%>
{"result" : "success"}
<%
} catch(Exception e){
%>
{"result" : "failure"}
<%
e.printStackTrace();
} finally{
DBUtil.executeClose(null, pstmt, conn);
}
%>
<%@ page language="java" contentType="text/plain; charset=UTF-8"
pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@page import="java.util.Date"%>
<%@ page import="kr.util.DBUtil"%>
<%@ page import="java.sql.Connection"%>
<%@ page import="java.sql.PreparedStatement"%>
<%@ page import="java.sql.ResultSet"%>
[<%
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
String sql = null;
try{
conn = DBUtil.getConnection();
sql = "SELECT*FROM todo ORDER BY id DESC";
pstmt = conn.prepareStatement(sql);
rs = pstmt.executeQuery();
while(rs.next()){
int id = rs.getInt("id");
String todo = rs.getString("todo");
Date created = rs.getDate("created");
int completed = rs.getInt("completed");
if(rs.getRow() > 1){ // 첫 번째 내용은 쉼표가 들어가지 않음
out.println(",");
}
%>
{
"id" : <%=id%>,
"todo" : "<%=todo%>",
"created" : "<%=created%>",
"completed" : <%=completed%>
}
<%
}
} catch(Exception e){
e.printStackTrace();
} finally{
DBUtil.executeClose(rs, pstmt, conn);
}
%>]
<%@ page language="java" contentType="text/plain; charset=UTF-8"
pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@ page import="kr.util.DBUtil"%>
<%@ page import="java.sql.Connection"%>
<%@ page import="java.sql.PreparedStatement"%>
<%
request.setCharacterEncoding("utf-8");
int id = Integer.parseInt(request.getParameter("id"));
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try{
conn = DBUtil.getConnection();
sql = "DELETE FROM todo WHERE id=?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);
pstmt.executeUpdate();
%>
{"result" : "success"}
<%
} catch(Exception e){
%>
{"result" : "failure"}
<%
e.printStackTrace();
} finally{
DBUtil.executeClose(null, pstmt, conn);
}
%>
<%@ page language="java" contentType="text/plain; charset=UTF-8"
pageEncoding="UTF-8" trimDirectiveWhitespaces="true"%>
<%@page import="java.sql.PreparedStatement"%>
<%@ page import="kr.util.DBUtil"%>
<%@ page import="java.sql.Connection"%>
<%@ page import="java.sql.PreparedStatement"%>
<%@ page import="java.sql.ResultSet"%>
<%
request.setCharacterEncoding("utf-8");
int id = Integer.parseInt(request.getParameter("id"));
int completed = Integer.parseInt(request.getParameter("completed"));
// Toggle 형태로 움직일 수 있게 만들어줌
if(completed == 0) completed = 1;
else completed = 0;
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try {
conn = DBUtil.getConnection();
sql = "UPDATE todo SET completed=? WHERE id=?";
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1,completed);
pstmt.setInt(2, id);
pstmt.executeUpdate();
%>
{"result":"success"}
<%
} catch (Exception e) {
%>
{"result":"failure"}
<%
e.printStackTrace();
} finally {
DBUtil.executeClose(null, pstmt, conn);
}
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- 모바일 장치에서 웹사이트가 원하는 사이즈로 보여지게 처리 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>To-Do List</title>
<!-- BootStrap CSS 링크 -->
<link href="https://unpkg.com/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet">
<style type="text/css">
body {
margin: 0;
padding: 0;
font-family: sans-serif;
}
.title{
text-align: center;
font-weight: bold;
font-size: 20pt;
}
.todo-done{
text-decoration: line-through;
}
.container {
padding: 10px;
}
.pointer{
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<div class="card card-body">
<div class="title">To-Do List</div>
</div>
<div class="card card-default">
<div class="card-body">
<div class="row mb-3">
<div class="col">
<div class="input-group">
<input type="text" class="form-control" name="msg" placeholder="Insert To-Do" id="todo">
<span class="btn btn-primary input-group-addon" id="add_btn">추가</span>
</div>
</div>
</div>
<div class="row">
<div class="col">
<ul class="list-group" id="list"></ul>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="../js/jquery-3.7.1.min.js"></script>
<script type="text/javascript">
// 목록 처리
function selectList(){
// 서버와 통신
$.ajax({
url:'getTodoList.jsp',
dataType : 'json',
success:function(param){
$('#list').empty();
$(param).each(function(index,item){
let output = '';
if(item.completed){ // 할 일 체크하면 1 = true
output += '<li class="list-group-item list-group-item-success">'
output += '<span class="pointer todo-done check-btn" id="'+item.id+'" data-check="'+item.completed+'">'+item.todo+' (완료)</span>'
} else{ // 할 일 체크가 0이면 false
output += '<li class="list-group-item">'
output += '<span class="pointer check-btn" id="'+item.id+'" data-check="'+item.completed+'">'+item.todo+' (작성일 : '+item.created+')</span>'
}
output += '<span class="float-end badge bg-secondary pointer delete-btn" id="'+item.id+'">삭제</span>'
output += '</li>'
$('#list').append(output);
});
},
error : function(){
alert('Network Error Occurred');
}
});
};
// 초기 데이터 설정
selectList();
// 등록 처리 함수
function addTodo(){
if($('#todo').val().trim()==''){
alert('할 일을 입력하세요.');
$('#todo').val('').focus();
return;
}
// 서버와 통신
$.ajax({
url:'insertTodo.jsp',
type : 'post',
data : {todo:$('#todo').val()},
dataType : 'json',
success : function(param){ // 할 일 등록에 성공
if(param.result == 'success'){
// alert('등록 성공하였습니다.');
// => 등록된 데이터가 바로 보여지기 때문에 생략 가능
// 입력창 초기화
$('#todo').val('');
// 목록 호출
selectList();
} else{ // 할 일 등록에 실패
alert('등록 실패하였습니다.')
}
},
error : function(param){
alert('Network Error Occurred');
}
});
};
// 등록 key 이벤트 연결
$('#todo').keydown(function(event){
if(event.keyCode == 13){ // 엔터키를 치는 경우
addTodo();
}
});
// add button 눌렀을 때
$('#add_btn').click(function(event){
addTodo();
});
// 삭제 이벤트 연결
$(document).on('click','.delete-btn',function(){
// 서버와 통신
$.ajax({
url:'deleteTodo.jsp',
type:'post',
data:{id:$(this).attr('id')},
dataType :'json',
success:function(param){
if(param.result=='success'){
// 삭제 성공했을 때는 바로 없어지기 때문에 alert 따로 명시 안 함
selectList();
} else{
alert('삭제에 실패하였습니다.');
}
},
error:function(){
alert('Network Error Occurred');
}
});
});
// 할 일 체크 이벤트 연결
$(document).on('click','.check-btn',function(){
$.ajax({
url:'updateTodo.jsp',
type:'post',
data:{id:$(this).attr('id'),completed:$(this).attr('data-check')},
dataType :'json',
success:function(param){
if(param.result=='success'){
selectList();
} else{
alert('할 일 체크 오류 발생');
}
},
error:function(){
alert('Network Error Occurred');
}
});
});
</script>
</body>
</html>

웹 프로그래밍에서 데이터의 표현을 목적으로 사용
<jsp:useBean id=”빈이름” class=”자바클래스이름” scope=”범위”/>
JSP에서 자바빈 객체를 생성할 때 사용
<jsp:setProperty name=”자바빈” property=”이름” value=”값” />
자바빈 객체의 프로퍼티 값 설정
<jsp:getProperty name=”자바빈” property=”이름” >
프로퍼티의 값을 출력하기 위해 사용
VO(Value Object) , 자바빈: 데이터 베이스 연동시 데이터를 관리하는 객체
package kr.web.member;
public class MemberVO {
// 멤버 변수 (property)
private String id;
private String password;
private String name;
private String email;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
private String address;
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입 입력 Form</title>
</head>
<body>
<form action="processJoining.jsp" method="post">
아이디 <input type="text" name="id" size="10"><br>
비밀번호 <input type="password" name="password" size="10"><br>
이름 <input type="text" name="name" size="10"><br>
이메일 <input type="email" name="email" size="10"><br>
주소 <input type="text" name="address" size="30"><br>
<input type="submit" value="회원 가입"><br>
</form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="kr.web.member.MemberVO"%>
<%
// 전송된 데이터 인코딩 타입 지정
request.setCharacterEncoding("UTF-8");
// 자바 빈 생성
MemberVO member = new MemberVO();
member.setId(request.getParameter("id"));
member.setPassword(request.getParameter("password"));
member.setName(request.getParameter("name"));
member.setEmail(request.getParameter("email"));
member.setAddress(request.getParameter("address"));
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입</title>
</head>
<body>
아이디 : <%= member.getId() %><br>
비밀번호 : <%= member.getPassword() %><br>
이름 : <%= member.getName() %><br>
이메일 : <%= member.getEmail() %><br>
주소 : <%= member.getAddress() %><br>
</body>
</html>
MemberVO, Form 코드는 동일하기 때문에 생략
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
request.setCharacterEncoding("UTF-8");
%>
<jsp:useBean id="member" class="kr.web.member.MemberVO"/>
<jsp:setProperty name="member" property="*" />
<!-- *은 모든 property를 뜻한다-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
아이디 : <jsp:getProperty property="id" name="member"/><br>
비밀번호 : <jsp:getProperty property="password" name="member"/><br>
이름 : <jsp:getProperty property="name" name="member"/><br>
이메일 : <jsp:getProperty property="email" name="member"/><br>
주소 : <jsp:getProperty property="address" name="member"/><br>
</body>
</html>

데이터베이스와 연결된 커넥션을 미리 만들어서 풀(pool) 속에 저장해 두고 있다가 필요할 때에 커넥션을 풀(pool)에서 가져다 쓰고 다시 풀(pool)에 반환하는 기법을 의미
커넥션 풀을 사용하면 데이터베이스와의 연결 관리가 효율적으로 이루어져서 성능과 안정성을 높일 수 있다.3

JDBC(Java Database Connectivity)에서 데이터베이스와의 연결을 관리하기 위한 인터페이스이다.주로 커넥션 풀링(Connection Pooling)을 구현하는 데 사용된다.서버 환경에서 데이터베이스와의 안정적인 연결을 관리하는 데 중요한 역할을 한다. 커넥션 풀을 구현할 때 DataSource 인터페이스를 활용하여 데이터베이스 연결을 효율적으로 관리할 수 있다.
package kr.util;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
public class DBUtil {
// Connection 객체를 생성해서 반환
public static Connection getConnection() throws Exception{
Context initCtx = new InitialContext();
DataSource ds = (DataSource)initCtx.lookup("java:comp/env/jdbc/xe");
return ds.getConnection();
}
// 자원 정리
public static void executeClose(ResultSet rs, PreparedStatement pstmt, Connection conn) {
if(rs!=null) try {rs.close();} catch(SQLException e) {}
if(pstmt!=null) try {pstmt.close();} catch(SQLException e) {}
if(conn!=null) try {conn.close();} catch(SQLException e) {}
}
}
package kr.member.vo;
import java.sql.Date;
public class MemberVO {
private int num;
private String id;
private String name;
private String passwd;
private String email;
private String phone;
private Date reg_date;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPasswd() {
return passwd;
}
public void setPasswd(String passwd) {
this.passwd = passwd;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public Date getReg_date() {
return reg_date;
}
public void setReg_date(Date reg_date) {
this.reg_date = reg_date;
}
}
package kr.member.dao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import kr.member.vo.MemberVO;
import kr.util.DBUtil;
public class MemberDAO {
/*
* 싱글턴 패턴은 생성자 private으로 지정해서 외부에서 호출할 수 없도록 처리하고
* static 메서드를 호출해서 객체가 한번만 생성되고
* 생성된 객체를 공유할 수 있도록 처리하는 방식을 의미한다.
*/
private static MemberDAO instance = new MemberDAO();
public static MemberDAO getInstance() {
return instance;
}
private MemberDAO() {
}
// 회원 가입
public void insertMember(MemberVO member) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
String sql = null;
try {
conn = DBUtil.getConnection();
sql = "INSERT INTO smember(num,id,name,passwd,email,phone) VALUES(smember_seq.nextval,?,?,?,?,?)";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, member.getId());
pstmt.setString(2, member.getName());
pstmt.setString(3, member.getPasswd());
pstmt.setString(4, member.getEmail());
pstmt.setString(5, member.getPhone());
pstmt.executeUpdate();
}catch(Exception e) {
throw new Exception(e);
}finally {
DBUtil.executeClose(null, pstmt, conn);
}
}
// 회원 상세 정보
public MemberVO getMember(int num) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
MemberVO member = null;
String sql = null;
return member;
}
// 아이디 중복 체크, 로그인 체크
public MemberVO checkMember(String id) throws Exception {
Connection conn = null;
PreparedStatement pstmt = null;
ResultSet rs = null;
MemberVO member = null;
String sql = null;
try {
conn = DBUtil.getConnection();
sql="SELECT * FROM smember WHERE id=?";
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, id);
rs = pstmt.executeQuery();
if(rs.next()) {
member = new MemberVO();
member.setId(rs.getString("id"));
member.setNum(rs.getInt("num"));
member.setPasswd(rs.getString("passwd"));
}else {
}
}catch (Exception e) {
throw new Exception(e);
}finally {
DBUtil.executeClose(rs, pstmt, conn);
}
return member;
}
// 회원 정보 수정
public void updateMember(MemberVO member) throws Exception {
}
// 회원 탈퇴(정보 삭제)
public void deleteMember(int num) throws Exception {
}
}
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<!-- 컨텍스트 경로로 지정해도 문제 없고, 컨텍스트 명이 바뀌더라도 문제 발생이 일어나지 않는다 -->
<link rel="stylesheet" href="<%= request.getContextPath() %>/css/style.css">
<title>회원 관리 Main</title>
</head>
<body>
<%
String user_id = (String)session.getAttribute("user_id");
%>
<div class="page-main">
<h1>회원관리 메인</h1>
<div class="align-right">
<%
if(user_id == null){ // 로그인 실패
%>
<a href="registerUserForm.jsp">회원 가입</a>
<a href="loginForm.jsp">로그인</a>
<%
} else{ // 로그인 성공
%>
<a href="myPage.jsp">마이페이지</a>
<b><%=user_id %></b> 로그인 중
<a href="logout.jsp">로그아웃</a>
<%
}
%>
</div>
</div>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입</title>
<link rel="stylesheet" href="<%= request.getContextPath() %>/css/style.css">
</head>
<body>
<div class="page-main">
<h1>회원 가입</h1>
<form action="registerUser.jsp" method="post" id="register_form">
<ul>
<li>
<label for="id">아이디</label>
<input type="text" name="id" id="id" size="7" maxlength="12" autocomplete="off" class="input-check">
<input type="button" id="confirm_id" value="ID 중복 확인">
<span id="id_signed"></span>
</li>
<li>
<label for="name">이름</label>
<input type="text" name="name" id="name" class="input-check" maxlength="10">
</li>
<li>
<label for="passwd">비밀번호</label>
<input type="password" name="passwd" id="passwd" class="input-check" maxlength="12">
</li>
<li>
<label for="email">이메일</label>
<input type="email" name="email" id="email" class="input-check" maxlength="50">
</li>
<li>
<label for="phone">전화번호</label>
<input type="text" name="phone" id="phone" class="input-check" maxlength="15">
</li>
</ul>
<div class="align-center">
<input type="submit" value="Register">
<input type="button" value="Home" onclick="location.href='main.jsp'">
</div>
</form>
</div>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ page import="kr.member.dao.MemberDAO"%>
<%
// 전송된 데이터 인코딩 타입 지정
request.setCharacterEncoding("UTF-8");
%>
<jsp:useBean id="member" class="kr.member.vo.MemberVO" />
<%-- request로부터 전송된 데이터를 읽어들여 자바빈에 저장 --%>
<jsp:setProperty property="*" name="member" />
<%
MemberDAO dao = MemberDAO.getInstance();
dao.insertMember(member);
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>회원 가입</title>
<link rel="stylesheet" href="<%= request.getContextPath() %>/css/style.css">
</head>
<body>
<div class="page-main">
<h1>회원 가입 완료</h1>
<div class="result-display">
<div class="align-center">
회원가입 성공!
<p>
<button onclick="location.href='main.jsp'">Home</button>
</div>
</div>
</div>
</body>
</html>
