회원가입 사이트 만들기

✒️ 2025-05-26 11:08 내용 수정


실습 목표

실습 흐름

  1. 데이터베이스에 테이블 및 시퀀스, 필요 시 샘플 데이터 추가
  2. 데이터베이스에 연결 : context.xml 파일, 라이브러리(JDBC)
  3. 테이블의 정보를 저장할 DTO 클래스 생성
  4. 데이터베이스에서 조회, 추가, 삭제를 수행하는 DAO 클래스 생성
  5. 조회 결과를 확인 및 삭제, 회원 가입할 JSP 생성
  6. DAO 클래스 객체를 생성하고, JSP와 연결할 Servlet 생성
  7. Servlet에서 코드 실행 시 결과 확인

DB에 테이블 추가

--시퀀스
CREATE SEQUENCE SEQ_MYUSER_IDX;

--테이블
CREATE TABLE MYUSER(
	IDX NUMBER(3) PRIMARY KEY,
	NAME VARCHAR2(100) NOT NULL,
	ID VARCHAR2(100) NOT NULL, UNIQUE,
	PWD VARCHAR2(100) NOT NULL
);

DB 연결

  1. context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context>
	<Resource 
	        auth="Container" 
      		name="jdbc/oracle_test"
      		type="javax.sql.DataSource"
      		driverClassName="oracle.jdbc.driver.OracleDriver"
      		factory="org.apache.commons.dbcp.BasicDataSourceFactory"
      		url="jdbc:oracle:thin:@localhost:1521:xe"
      		username="계정명" password="비밀번호" 
      		maxActive="20" maxIdle="10" maxWait="1"/>
</Context>
  1. 라이브러리
    • 라이브러리에 lomboc 추가하여 사용
파일
commons-collections-3.2.1.jar
commons-dbcp-1.2.2.jar
commons-pool-1.4.jar
ojdbc8-23.3.0.23.09.jar
lomboc.jar
  1. service용 DBService.java
package service;

import java.sql.Connection;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;

public class DBConnection {

	static DBConnection db = null;
	DataSource ds;

	// singleton pattern으로 생성
	public static DBConnection getInstance() {
		if(db == null) {
			db = new DBConnection();
		}
		return db;
	}

	// 생성자에서 Context 객체와 DataSource 초기화
	public DBConnection() {
		try {
			InitialContext ic = new InitialContext();
			Context ctx = (Context)ic.lookup("java:comp/env");
			ds = (DataSource)ctx.lookup("jdbc/oracle_test");
		
		} catch (NamingException e) {
			e.printStackTrace();
		}
	}

	// 생성자에서 준비한 정보로 DB에 연결하여 Connection 객체 얻기
	public Connection getConnection() {
		Connection connec = null;
		try {
			connec = ds.getConnection();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return connec;
	}
}

Ajax

  1. HttpRequest.js
var xhr = null;

function createRequest() {
	if (xhr != null) {
		return;
	}
	if (window.ActiveXObject) {
		xhr = new ActiveXObject("Microsoft.XMLHTTP"); // IE 환경
	} else {
		xhr = new XMLHttpRequest(); // 기타 브라우저 환경
	}
}

function sendRequest(url, param, callback, method) {

	// HttpRequest 생성
	createRequest();

	// 전송 타입 구분
	var httpMethod = (method != 'POST' && method != 'post') ? 'GET' : 'POST';

	// 파라미터 구분
	var httpParam = (param == null || param == '') ? null : param;

	// 접근 url
	var httpURL = url;

	// 요청 방식이 GET이고 전달할 파라미터가 있다면 새 url 경로 제작
	if (httpMethod == 'GET' && httpParam != null) {
		httpURL = httpURL+'?'+httParam;
	}

	// 서버로 보낼 Ajax 요청 형식
	xhr.open(httpMethod, httpURL, true);

	// requestHeader 설정 : Content-Type 지정
	xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

	// 작업이 완료된 후 호출할 callback 메소드 지정
	xhr.onreadystatechange = callback;

	// Ajax 요청을 서버로 전달
	xhr.send(httpMethod == 'POST' ? httpParam : null);
}

DAO와 DTO

  1. dto
package dto;

import lombok.Data;

@Data

public class UserDTO {
	int idx;
	String name;
	String id;
	String pwd;
}
  1. dao
package dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import dto.UserDTO;
import service.DBService;

public class UserDAO {

	static UserDAO single = null;

	public static UserDAO getInstance() {
		//생성되지 않았으면 생성
		if (single == null)
			single = new UserDAO();
		//생성된 객체정보를 반환
		return single;
	}
	
	// 회원 정보 조회
	public List<UserDTO> selectList() {

		List<UserDTO> list = new ArrayList<UserDTO>();
		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String sql = "SELECT * FROM MYUSER ORDER BY IDX DESC";

		try {
			//1.Connection얻어온다
			conn = DBService.getInstance().getConnection();
			//2.명령처리객체정보를 얻어오기
			pstmt = conn.prepareStatement(sql);

			//3.결과행 처리객체 얻어오기
			rs = pstmt.executeQuery();

			while (rs.next()) {
				UserDTO dto = new UserDTO();
				
				dto.setIdx(rs.getInt("idx"));
				dto.setName(rs.getString("name"));
				dto.setId(rs.getString("id"));
				dto.setPwd(rs.getString("pwd"));

				//ArrayList추가
				list.add(dto);
			}

		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		} finally {

			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}

		return list;
	}
	
	// 회원 추가
	public int insert(UserDTO dto) {
		int res = 0;

		Connection conn = null;
		PreparedStatement pstmt = null;

		String sql = "INSERT INTO MYUSER VALUES(SEQ_MYUSER_IDX.nextVal, ?, ?, ?)";

		try {
			//1.Connection획득
			conn = DBService.getInstance().getConnection();
			//2.명령처리객체 획득
			pstmt = conn.prepareStatement(sql);

			//3.pstmt parameter 채우기
			pstmt.setString(1, dto.getName());
			pstmt.setString(2, dto.getId());
			pstmt.setString(3, dto.getPwd());
			
			//4.DB로 전송(res:처리된행수)
			res = pstmt.executeUpdate();

		} catch (Exception e) {
			e.printStackTrace();
		} finally {

			try {
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return res;
	}
	
	// 중복 조회
	public UserDTO selectOne(String id) {

		UserDTO dto = null;

		Connection conn = null;
		PreparedStatement pstmt = null;
		ResultSet rs = null;
		String sql = "SELECT * FROM MYUSER WHERE ID=?";

		try {
			//1.Connection얻어온다
			conn = DBService.getInstance().getConnection();
			//2.명령처리객체정보를 얻어오기
			pstmt = conn.prepareStatement(sql);

			//3.pstmt parameter 설정
			pstmt.setString(1, id);
			
			//4.결과행 처리객체 얻어오기
			rs = pstmt.executeQuery();

			if (rs.next()) {
				// 1 건이라도 검색되면 null이 아니게 설정
				dto = new UserDTO();
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {

			try {
				if (rs != null)
					rs.close();
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}

		return dto;
	}
	
	// 회원 제거
	public int delete(int idx) {
		int res = 0;

		Connection conn = null;
		PreparedStatement pstmt = null;

		String sql = "DELETE FROM MYUSER WHERE IDX=?";

		try {
			//1.Connection획득
			conn = DBService.getInstance().getConnection();
			//2.명령처리객체 획득
			pstmt = conn.prepareStatement(sql);

			//3.pstmt parameter 채우기
			pstmt.setInt(1, idx);
				
			//4.DB로 전송(res:처리된행수)
			res = pstmt.executeUpdate();

		} catch (Exception e) {
			e.printStackTrace();
		} finally {

			try {
				if (pstmt != null)
					pstmt.close();
				if (conn != null)
					conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return res;
	}
}

Servlet

  1. 회원 조회
package action;

import java.io.IOException;
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 dao.UserDAO;
import dto.UserDTO;


@WebServlet("/check_id")
public class MemberCheckAction extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// check_id?id=x
		String id = request.getParameter("id");
		
		UserDTO dto = UserDAO.getInstance().selectOne(id);
			
		String res = "no";
		
		if (dto == null) {
			res = "yes";
		}
		
		String result = String.format("[{'res':'%s'}]", res);
		response.getWriter().print(result);
	}

}
  1. 회원 리스트
package action;

import java.io.IOException;
import java.util.List;

import javax.servlet.RequestDispatcher;
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 dao.UserDAO;
import dto.UserDTO;


@WebServlet("/member_list")
public class MemberListAction extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// 회원 목록 얻어오기
		List<UserDTO> list = UserDAO.getInstance().selectList();
		
		// list를 request 영역에 바인딩
		request.setAttribute("list", list);
		
		// member_list.jsp에서 el 표현식을 사용할 수 있도록
		// 포워딩 지정
		RequestDispatcher disp = request.getRequestDispatcher("member_list.jsp");
		disp.forward(request, response);
	}

}
  1. 회원 추가
package action;

import java.io.IOException;
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 dao.UserDAO;
import dto.UserDTO;


@WebServlet("/insert")
public class MemberInsertAction extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

		// insert?id=X&pwd=X&name=X
		request.setCharacterEncoding("utf-8");
		
		String id = request.getParameter("id");
		String pwd = request.getParameter("pwd");
		String name = request.getParameter("name");
		
		UserDTO dto = new UserDTO();
		dto.setId(id);
		dto.setPwd(pwd);
		dto.setName(name);
		
		int res = UserDAO.getInstance().insert(dto);
		
		if (res >= 1) {
			response.sendRedirect("member_list");
		}
	}

}
  1. 회원 삭제
package action;

import java.io.IOException;
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 dao.UserDAO;

@WebServlet("/member_del")
public class MemberDelAction extends HttpServlet {
	private static final long serialVersionUID = 1L;

	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		request.setCharacterEncoding("utf-8");
		
		int idx = Integer.parseInt(request.getParameter("idx"));
		
		int res = UserDAO.getInstance().delete(idx);
		
		String param = "no";
		
		if (res >= 1) {
			param = "yes";
		}
		
		String resultStr = String.format("[{'param':'%s'}]", param);
		
		response.getWriter().print(resultStr);
	}

}

JSP

  1. 회원 추가 JSP
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
	<style type="text/css">
		table{margin:0 auto;}
	</style>
	<script src="js/HttpRequest.js"></script>
	<script type="text/javascript">
	
		// 아이디 중복체크 여부
		var b_idCheck = false;
		
		function send(f) {
			var id = f.id.value.trim();
			var name = f.name.value.trim();
			var pwd = f.pwd.value.trim();
			
			// 유효성 검사
			if (id == '') {
				alert("id를 입력하세요");
				return;
			}
			if (!b_idCheck) {
				alert("아이디 중복 체크를 하세요");
				return;
			}
			if (name == '') {
				alert("이름을 입력하세요");
				return;
			}			
			if (pwd == '') {
				alert("비밀번호를 입력하세요");
				return;
			}
			
			f.method = "POST";
			f.action = "insert";
			f.submit();
		}
		
		function check_id() {
			var id = document.getElementById("id").value.trim();
			
			// 유효성 검사
			if (id == '') {
				alert("id를 입력하세요");
				return;
			}
			
			// ajax 사용
			// 완전히 새로고침하면 textfield의 내용이 사라지므로 일부분만 로딩
			var url = "check_id";
			var param = "id="+id;
			
			sendRequest(url, param, resultFn, "POST");
		}
		
		function resultFn() {
			if(xhr.readyState == 4 && xhr.status == 200) {
				var data = xhr.responseText;
				
				var json = eval(data);
				
				if(json[0].res == "no") {
					alert("이미 사용 중인 아이디 입니다.");
					return;
				} else {
					alert("사용 가능한 아이디 입니다.");
					b_idCheck = true;
				}
			}
		}
		
		function che() {
			b_idCheck = false;
		}
	</script>
</head>
<body>
	<form>
		<table border="1">
			<caption>:::회원가입:::</caption>
			<tr>
				<th>아이디</th>
					<td>
						<!-- onchange : input 태그의 내용이 변경될 때 발생하는 이벤트 -->
						<input name="id" id="id" onchange="che()">
						<input type="button" value="중복체크" onclick="check_id()">
					</td>
			</tr>
			<tr>
				<th>이름</th>
				<td>
					<input name="name">
				</td>
			</tr>
			<tr>
				<th>비밀번호</th>
				<td>
					<input type="password" name="pwd">
				</td>
			</tr>
			<tr>
				<td colspan="2" align="center">
					<input type="button" value="가입" onclick="send(this.form)">
					<input type="button" value="취소" onclick="location.href='member_list'">
				</td>
			</tr>
		</table>
	</form>
</body>
</html>
  1. 회원 리스트 JSP
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
	<style>
		table{border-collapse:collapse;
			  text-align:center;}
		th{width:200px; height:60px;}
	</style>
	<script src="js/HttpRequest.js"></script>
	<script type="text/javascript">
		function del(idx) {
			if (!confirm("삭제하시겠습니까?")) {
				return;
			}
			
			var url = "member_del";
			var param = "idx="+idx;
			
			sendRequest(url, param, resultFn, "POST");
		}
		
		function resultFn() {
			if(xhr.readyState == 4 && xhr.status == 200) {
				var data = xhr.responseText;
				
				var json = eval(data);
				
				if(json[0].param == "no") {
					alert("회원 삭제에 실패했습니다.");
				} else {
					alert("회원 삭제를 성공했습니다.");
				}
				
				location.href = "member_list";
			}
		}
	</script>
</head>
<body>
	<table border="1">
		<tr>
			<td colspan="5" align="center">
				<input type="button" value="회원가입" onclick="location.href='member_insert_form.jsp';">
			</td>
		</tr>
		<tr>
			<th>회원번호</th>
			<th>이름</th>
			<th>아이디</th>
			<th>비밀번호</th>
			<th>비고</th>
		</tr>
		<c:forEach var="dto" items="${list}">
			<tr>
				<td>${dto.idx}</td>
				<td>${dto.name}</td>
				<td>${dto.id}</td>
				<td>${dto.pwd}</td>
				<td>
					<input type="button" value="삭제" onclick="del('${dto.idx}');">
				</td>
			</tr>
		</c:forEach>
	</table>
</body>
</html>

완성된 모습

  1. ListAction Servlet에서 실행하면 회원 정보가 조회된다.
    회원가입 1.png

  2. 회원가입 버튼을 누르고 중복된 아이디를 누른 후에 중복 확인을 하면 경고창이 뜬다.
    회원가입 2.png

  3. 만약 중복 체크를 안하면 가입하지 못하도록 경고가 뜨면서 새로운 창으로 넘어가지지 않는다.
    회원가입 8.png

  4. 중복된 아이디가 아니라면 가입 조건이 충족된다.
    회원가입 3.png

  5. 가입이 완료되면 다시 회원 정보창에 추가된 계정이 보인다.
    회원가입 4.png

  6. 삭제 버튼을 누르면 안내창이 나온다. 확인을 누르면 삭제가 진행된다.
    회원가입 5.png
    회원가입 6.png

  7. 삭제가 제대로 진행된 것을 확인할 수 있다.
    회원가입 7.png