[Java] CRUD 토이프로젝트 - 1

Hyeonseok Jeong·2023년 8월 23일
0

Java

목록 보기
1/5

그동안 Java를 배우며 시간을 지냈는데 드디어
Java 와 Servlet, JSP 등을 학습하여 간단한 토이 프로젝트를 만들게 되었다

이번에 진행한 토이 프로젝트는 CRUD 프로젝트이다

내용은 정말 CRUD를 학습하기 위한 토이 프로젝트 이므로 딱히 주제는 없고
로그인, 회원가입, 게시판 리스트, 게시판 디테일, 게시판 등록, 관리자(모든 게시판 내용 삭제 가능) 정도를 구현 할려고 한다.

진행상항

view 는 간단하게 애용하던 vscode를 사용해서 구현하고 이후 파일을 옮겨 왔다
(그런데 js 가 제대로 적용이 안되는 이슈가 있었다)

그리고 먼저 회원가입 기능을 구현해 보기위해

  • controller
  • service
  • dto
  • dao

패키지를 만들어 signUp class 파일을 구현 하였다.

// signUpController

package com.CRUDp.web.client.controller;

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 com.CRUDp.web.client.service.SignUpService;

@WebServlet("/client/signUp")
public class SignUpController extends HttpServlet {
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

		req.getRequestDispatcher("/WEB-INF/view/client/signUp/signUp.jsp").forward(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

		String email = req.getParameter("email");
		String pwd = req.getParameter("pwd");
		String pwdCh = req.getParameter("pwd-ch");
		String name = req.getParameter("name");
		String phone1 = req.getParameter("phone1");
		String phone2 = req.getParameter("phone2");
		String phone3 = req.getParameter("phone3");
		String birth_ = req.getParameter("birth");

		SignUpService service = new SignUpService();
		String result = service.setUserSignUp(email, pwd, pwdCh, name, phone1, phone2, phone3, birth_);

		System.out.println(result);

		if (result.equals("성공적으로 회원가입이 완료되었습니다")) {
			resp.sendRedirect("signIn");
		} else {
			resp.sendRedirect("signUp");
		}

	}
}

확실히 처음 프론트엔드 공부를 할때 처럼 삐걱이기 시작했다
분명 먼가 되긴 되는데 부족한것 같은데 그 부족한 부분을 모르겠다.
(아마 저 if문을 사용해서 처리한 부분이 이상한 것 같긴하다)

다음으로는 service 로직이다.

package com.CRUDp.web.client.service;

import java.security.NoSuchAlgorithmException;
import java.sql.Date;

import com.CRUDp.web.client.dao.UserDao;
import com.CRUDp.web.client.dto.UserDto;
import com.CRUDp.web.security.Sha256;

public class SignUpService {

	public String setUserSignUp(String email_, String pwd_, String pwdCh_, String name_, String phone1_, String phone2_,
			String phone3_, String birth_) {
		System.out.printf("email : %s\n", email_);
		System.out.printf("pwd : %s\n", pwd_);
		System.out.printf("pwdCh : %s\n", pwdCh_);
		System.out.printf("name : %s\n", name_);
		System.out.printf("phone1 : %s\n", phone1_);
		System.out.printf("phone2 : %s\n", phone2_);
		System.out.printf("phone3 : %s\n", phone3_);
		System.out.printf("birth : %s\n", birth_);

		String email = null;
		String pwd = null;
		String name = null;
		String phoneNumber = null;
		Date birth = null;

		// 1. email 검증
		// DB 에서 email 데이터를 조회하여 같은 Email이 존재하는경우 err 메세지를 띄워줘야함
		boolean emailState = false;
		UserDao userDao = new UserDao();

		if (email_ != null && !email_.equals("")) {
			emailState = userDao.selectEmailCheckDao(email_);
		}
		if (emailState) {
			email = email_;
		} else {
			return "이미 존재하는 Email 입니다";
		}

		// 2. pwd 검증
		// 패스워드의 경우 대문자 소문자 특수문자 숫자 의 조합이 8자이상 15자이하 인지 정규식을 통해서 검증
		// 또한 해싱 작업을 통해서 해당 비밀번호를 암호화 해야함

		Sha256 sha256 = new Sha256();

		if (pwd_ != null && pwd_.matches("^(?=.*[a-zA-Z])(?=.*\\d)(?=.*\\W).{8,15}$")) {
			try {
				pwd = sha256.encrypt(pwd_);
			} catch (NoSuchAlgorithmException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} else {
			return "패스워드 형식이 올바르지 않습니다";
		}

		// 3. pwdCh 검증
		// 앞서 하였던 password 검증을 통과한 pwd 와 일치하는지에 대하여 검증
		try {
			if (!pwd.equals(sha256.encrypt(pwdCh_))) {
				return "패스워드가 일치하지 않습니다";
			}
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// 4. phone number
		// phone1, phone2, phone3 에 대해서 xxx-yyyy-zzzz 와 같은 형식으로 포멧팅
		// phoneNumber 정규식 사용하여 검증 과정 필요
		if (phone1_ != null && phone2_ != null && phone3_ != null && !phone1_.equals("") && !phone2_.equals("")
				&& !phone3_.equals("")) {
			phoneNumber = phone1_ + "-" + phone2_ + "-" + phone3_;
		} else {
			return "전화번호를 등록하지 않았습니다.";
		}

		// 5. birth
		// String 타입에서 Date 타입으로 형 변환
		if (birth_ != null && !birth_.equals("")) {
			birth = Date.valueOf(birth_);
		} else {
			return "생일을 등록하지 않으셨습니다.";
		}

		// + name
		if (name_ != null && !name_.equals("")) {
			name = name_;
		} else {
			return "닉네임을 등록하지 않았습니다.";
		}

		// 6. user dto에 데이터 집어넣은후 dao에 데이터 전달
		UserDto user = new UserDto(email, pwd, name, birth, phoneNumber);

		UserDao insertUser = new UserDao();
		int state = insertUser.insertUserDao(user);

		if (state != 0) {
			return "성공적으로 회원가입이 완료되었습니다";
		}

		return "회원가입에 실패하였습니다";
	}

}

정말 이부분이 제일 회의적이라고 할 수 있다.
역시 독학에는 한계가 있는건지 아무리 봐도 만족스럽지가 않다 물론 배우는 과정이지만 아무리 그래도 저 어지러운 조건문들과 return 그리고 가장 어지러운 Password 해싱과정 이부분은 솔트를 추가해서 작업 해볼려고 했지만 처음에는 솔트 없이 기초적인 해싱으로 해볼려고 하였다.

그래서 암호화는 작동하긴 하지만 솔직히 내가 현역으로 취업하게 되면 나라도 저렇게 로직을 짜진 않을것 같다 이부분에서 가장 어지러움을 느꼈다.

그래도 다행이 코드 자체는 작동을 하여 우선 dao단으로 넘어가 남은 로직을 작성하였다.

package com.CRUDp.web.client.dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import com.CRUDp.web.client.dto.UserDto;

public class UserDao {

	// email 부분 dto 생성하여 User로 변경해야함
	public boolean selectEmailCheckDao(String email_) {
		boolean emailState = false;
		String email = "";

		String url = "jdbc:oracle:thin:@localhost:1521/xepdb1";
		String sql = "select * from member where email = ?";

		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
			Connection con = DriverManager.getConnection(url, "crud", "1111");
			PreparedStatement st = con.prepareStatement(sql);

			st.setString(1, email_);
			ResultSet rs = st.executeQuery();

			if (rs.next()) {
				email = rs.getString("email");
			}

			rs.close();
			st.close();
			con.close();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		if (email.equals("")) {
			emailState = true;
		}

		return emailState;
	}

	public int insertUserDao(UserDto user) {

		int result = 0;

		String url = "jdbc:oracle:thin:@localhost:1521/xepdb1";
		String sql = "insert into member(email, password, nickname, birth, phone_number) values(?,?,?,?,?)";

		try {
			Class.forName("oracle.jdbc.driver.OracleDriver");
			Connection con = DriverManager.getConnection(url, "crud", "1111");
			PreparedStatement st = con.prepareStatement(sql);

			st.setString(1, user.getEmail());
			st.setString(2, user.getPassword());
			st.setString(3, user.getNickname());
			st.setDate(4, user.getBirth());
			st.setString(5, user.getPhoneNumber());

			result = st.executeUpdate();

			st.close();
			con.close();

		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return result;
	}

	public void updateUserDao() throws ClassNotFoundException, SQLException {
		String url = "jdbc:oracle:thin:@localhost:1521/xepdb1";
		String sql = "";

		Class.forName("oracle.jdbc.driver.OracleDriver");
		Connection con = DriverManager.getConnection(url);
		PreparedStatement st = con.prepareStatement(sql);
	}
}

userDao 클래스이다.
이부분은 그래도 DBMS와 연결하는 작업만 존재해서 그런지 그렇게 로직이 어지럽진 않다
(물론 주니어인 내 기준에서)
그래도 아직 개선점이 눈에 보이긴 한다.
예를 들어 DB 연결 부분의 url 과 sql은 따로 두고 작업을 해도 되지 않을까 하는 생각이 든다.
가령 리액트에서 컴포넌트로 세분화 하듯이 저런 중복되는 부분들과 그룹으로 묶을 수 있는 부분들을 따로 두고 사용할 수 있지 않을까하는 생각이 든다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet"
	href="${pageContext.request.contextPath}/global/reset.css" />
<link rel="stylesheet"
	href="${pageContext.request.contextPath}/client/signUp/signUp.css" />
<title>CRUD</title>

</head>
<body>
	<div class="contain">
		<div class="box">
			<div class="link-box">
				<span class="home-link-span"> <a class="link"
					href="/client/signIn">LOGIN</a>
				</span> <span class="admin-link-span"> <a class="link"
					href="/admin/signIn">ADMIN LOGIN</a>
				</span>
			</div>
			<form class="form-box" action="" method="post">
				<div class="form-item-box">
					<div class="input-box">
						<input type="email" name="email" class="input email"
							placeholder="이메일을 작성해주세요" autofocus value="" />
					</div>
					<div class="err-box emailErr"></div>
				</div>
				<div class="form-item-box">
					<div class="input-box">
						<input type="password" name="pwd" class="input pwd"
							placeholder="비밀번호를 작성해주세요" />
					</div>
					<div class="err-box pwdErr"></div>
				</div>
				<div class="form-item-box">
					<div class="input-box">
						<input type="password" name="pwd-ch" class="input pwd-ch"
							placeholder="비밀번호를 다시 작성해주세요" />
					</div>
					<div class="err-box pwdChErr"></div>
				</div>
				<div class="form-item-box">
					<div class="input-box">
						<input type="text" name="name" class="input name"
							placeholder="닉네임을 작성해주세요" />
					</div>
					<div class="err-box nameErr"></div>
				</div>
				<div class="form-item-box">
					<div class="input-box">
						<select class="input phone1" name="phone1">
							<option value="010" selected>010</option>
							<option value="011">011</option>
							<option value="016">016</option>
						</select> <span class="desh">-</span> <input type="number" name="phone2"
							maxlength="4" oninput="maxLengthCheck(this)" class="input phone2"
							placeholder="전화번호" /> <span class="desh">-</span> <input
							type="number" name="phone3" maxlength="4"
							oninput="maxLengthCheck(this)" class="input phone3"
							placeholder="전화번호" />
					</div>
					<div class="err-box phoneErr"></div>
				</div>
				<div class="form-item-box">
					<div class="input-box">
						<input type="date" name="birth" class="input date" />
					</div>
					<div class="err-box dateErr"></div>
				</div>
				<div class="form-submit-box">
					<div class="submit-box">
						<input type="submit" class="input signUpSubmit" value="회원가입"
							disabled />
					</div>
				</div>
			</form>
		</div>
	</div>
	<script
		src="${pageContext.request.contextPath}/client/signUp/signUp.js"
		type="text/javascript">
		
	</script>
</body>
</html>

이부분은 signUp 의 JSP 인데 솔직히 지금은 백엔드 위주의 기능 공부를 하고 있어서 그렇게 신경쓰지는 못했다
사진으로 보자면 이런 정도?

아쉬운 부분들이 보이지만 중요한건 CRUD 기능 이기에 해당 기능에 집중할려고 한다.

(space때만 생각하면 css적용한거에 눈물이 나는데 이런점에서는 편한것 같다.)

아무튼 현재까지는 이런식으로 진행중이며 다행이 회원가입은 정상적으로 작동된다.
다음 기능으로는 로그인 기능을 마무리 해볼생각이다.

profile
풀스텍 개발자

0개의 댓글