[final project] day_1, day_2

김예은·2023년 8월 15일

자바 국비 교육

목록 보기
1/1

코드의 변화과정

day_1의 목표 '회원가입 페이지'의 코드 리뷰

요구사항

  1. 기존 사원 회원가입: 기존 사원의 경우 로그인->회원가입 페이지에서 사원번호를 직접 입력하여 회원가입을 진행할 수 있다.
    • value에 매개값 매핑하여 매개값이 없을 시 빈 input 태그 출력
  2. 신규 사원 회원가입: 신규 회원의 경우 이메일로 발송된 초대 링크를 통해 회원가입 페이지로 접속하여 회원가입을 진행할 수 있다.
    • 이메일로 초대 링크를 받을 경우 회원가입 링크의 매개값으로 사원번호 전달
    • 사원번호가 매개값으로 전달되었을 시 사번은 그냥 출력
    • input은 hidden으로 처리
  3. 사원번호 중복검사: 중복된 사원번호로 회원가입할 수 없다
    • 사원번호 입력 태그 옆에 중복검사 버튼 출력
    • 중복검사를 실행하지 않았을시 회원가입 버튼 비활성화
    • 중복검사 실행 결과 중복된 사원번호가 존재할 시 회원가입 버튼 비활성화
    • JQuery 사용
  4. 비밀번호 정규식 검사: 최소 8자 이상, 영문 대소문자 알파벳 중 적어도 하나 이상, 숫자 중 적어도 하나 이상, 특수문자 중 하나 이상
    • '영문 대/소문자와 특수문자를 포함해야 합니다' 팝업창 제시
    • JQuery 사용
  5. 비밀번호 일치불일치 검사: 비밀번호 확인 입력란을 생성하여 비밀번호 확인 검사 후 일치하지 않으면 회원가입이 진행되지 않는다
    • 비밀번호가 일치하지 않으면 비밀번호 확인 입력란 옆에 '비밀번호가 일치하지 않습니다' 문구 출력
    • 비밀번호가 일치하면 비밀번호 확인 입력란 옆에 '비밀번호가 일치합니다' 문구 출력
    • JQuery 사용
  6. 도로명 주소 조회: 주소 입력 시 도로명 주소를 조회하여 입력할 수 있다
    • DOM API로 구성된 KAKAO 주소찾기 API 사용
  • 회원가입 항목 공백검사: 사원번호, 사원명, 비밀번호, 성별, 전화번호, 주소 중 미입력된 항목이 있을 시 회원가입이 진행되지 않음
    • JQuery '모든 항목을 입력해주세요' 팝업창 제시

Script Source

  1. JQuery
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
  1. 카카오 도로명 주소 API
<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>


part1

1.1. 비밀번호 정규식 검사 함수 version_1
	$('#pw1').blur(function() {
		let pwPattern = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*()_+{}:;<>,.?~[\]\-]).{8,}$/;
        // 정규식 패턴은 양 끝에 슬래시를 포함
		
        if ( pwPattern.test( $('#pw1').val() ) ) { // 만약 패턴을 test(실행)할때 pw1 id의 값이 존재할시 사용가능한 비밀번호라고 알려주기
		// test 메서드는 해당 문자열이 정규식과 패턴이 일치하면 true를 반환
			$('#pwMsg1').html('<span style="color: green;">사용 가능한 비밀번호입니다.</span>'); //새롭게 span 태그를 만들어 알림
			console.log('비밀번호 정규식 일치');
		} else {
			$('#pwMsg1').html('<span style="color: red;">최소 8자 이상, 영문 대소문자, 숫자, 특수문자를 포함해주세요.</span>');
			console.log('비밀번호 정규식 불일치');
		}
	});

< body >에 < span > 태그를 만들지 않고, 메세지가 있을 때마다 text가 보이도록 html 메서드를 사용했으나, 코드 중복 및 비효율성을 인지.

1.2. 비밀번호 정규식 검사 함수 version_2

-코드의 재사용성과 유지보수를 용이하게 하기 위해, 정규식 패턴과 pw1 id값, 성공/실패 메세지를 담는 변수에 값 복사.
-< body >의 < input > 이 위치하는 곳에 < span >태그를 추가 생성. 성공/실패 알림에 따라 Msg text+css가 다르게 출력되도록 변경.

       
	function validatePassword() {
		let pwPattern = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*()_+{}:;<>,.?~[\]\-]).{8,}$/; // 정규식 패턴은 양 끝에 슬래시를 포함
		let pw1 = $('#pw1').val();
		let successMsg = '사용 가능한 비밀번호입니다.';
		let errorMsg = '최소 8자 이상, 영문 대소문자, 숫자, 특수문자를 포함해주세요.';
			
		if ( pwPattern.test(pw1) ) { // test 메서드는 해당 문자열이 정규식과 패턴이 일치하면 true를 반환
			$('#pwMsg1').text(successMsg).css('color', 'green');
			console.log('비밀번호 정규식 일치');
			return true;
		} else {
			$('#pwMsg1').text(errorMsg).css('color', 'red');
			console.log('비밀번호 정규식 불일치');
			return false;
		}
	}


part2

2.1. 비밀번호 일치불일치 검사 함수 version_1
$('#pw2').blur(function() { // 비밀번호 확인란에 입력 후 커서를 떼면 이벤트 발생
	if ( $('#pw1').val() != $('#pw2').val() ) {
		$('#pwMsg2').html('<span style="color: red;">비밀번호가 일치하지 않습니다.</span>');
		console.log('비밀번호 불일치');
	} else if ( $('#pw1').val() == $('#pw2').val() ) {
		$('#pwMsg2').html('<span style="color: green;">비밀번호가 일치합니다.</span>');
		console.log('비밀번호 일치');
	}
});
2.2. 비밀번호 일치불일치 검사 함수 version_2

part1처럼, 변수 생성 + 존재하는 < span >에 다른 메세지를 보이는 형식으로 변경

	function checkPasswordMatch() {
		let pw1 = $('#pw1').val();
		let pw2 = $('#pw2').val();
		let successMsg = '비밀번호가 일치합니다.';
		let errorMsg = '비밀번호가 일치하지 않습니다.';
			
		if ( pw1 == pw2 ) { 
			$('#pwMsg2').text(successMsg).css('color', 'green');
			console.log('비밀번호 일치');
			return true;
		} else { 
			$('#pwMsg2').text(errorMsg).css('color', 'red');
			console.log('비밀번호 불일치')
			return false;
		}
	}


part3

3.1. 사원번호 비동기 검사 함수 version_1
	$(document).ready(function() { // 웹 페이지가 모든 html 요소를 로드한 후에 내부(JQuery)의 코드를 실행하도록 보장
		let error = '${param.error}'; // error의 parameter값이 들어오면 변수에 값을 저장
		if (error == 'true') { // error가 있다면
			console.log('회원가입 실패'); // console에 알려주고
			alert('회원가입에 실패했습니다. 다시 시도해주세요.'); // 실패 메세지를 띄움
		}
			
		// 사원번호 검사
		$('#empNo').blur(function() { // 사용자가 사원번호 입력란에서 커서를 다른 곳으로 옮기면 실행
			if( $('#empNo').val().length < 11 ) { // 입력된 사원번호의 길이가 11자리를 넘지 않는다면 아래 코드 실행
            	
                // 비동기적으로 서버에 사원번호 검사 요청을 보냄
				$.ajax({
					url : '/checkEmpNo', // 처리하고자 하는 값을 RestController로 전달하며 처리 후 JSON 값을 받음
					type : 'post', // 비공개 형식으로 요청 보냄
					data : {empNo : $('#empNo').val()}, // empNo 값을 서버로 보냄
					success : function(response) { // 성공적인 응답을 받았을 경우 실행되는 함수
						console.log('사원번호 검사 실행');
						alert(response); // 서버에서 반환한 응답을 팝업 창으로 보여줌
					},
					error: function(error) { // 요청이 실패했을 경우 실행되는 함수
		                console.error('사원번호 검사 실패: ' + error);
		            }
				});
			} else {
				alert('사원번호는 7자리입니다.'); // 사원번호의 길이가 Integer 최대 정수값(11자리) 이상일 때, 사용자에게 경고 메시지를 보여줌
			}
		});

3.2. 사원번호 비동기 검사 함수 version_2
	let empNoValid = false; // 사원번호 검사 결과 변수 선언
		
	function checkEmpNo() {
		let empNo = $('#empNo').val();
			
		if ( empNo != '' ) { // 사원번호가 입력되어 있을 시
			if ( empNo.length < 11 ) { // Integer 타입의 최대 정수 범위 검사
				// 비동기 검사 실행
				$.ajax({
					url : '/checkEmpNo',
					type : 'post',
					data : {empNo : empNo},
					success : function(response) {
						console.log('사원번호 검사 실행');
							
						// 검사 결과에 따라 분기
						if (response.empInfoCnt == 0 || response.memberInfoCnt != 0) {
							$('#empNoMsg').text(response.resultMsg).css('color', 'red'); // 반환된 메세지를 출력
							console.log('사원번호 검사 결과 -> 가입 불가능');
							empNoValid = false;
						} else {
							$('#empNoMsg').text(response.resultMsg).css('color', 'green'); // 반환된 메세지를 출력
							console.log('사원번호 검사 결과 -> 가입 가능');
							empNoValid = true;
						}
					},
					error: function(error) {
		                console.error('사원번호 검사 실패: ' + error);
		                empNoValid = false;
		               }
				});
			} else { // 사원번호를 11자리 이상 입력할 경우
				$('#empNoMsg').text('사원번호는 7자리입니다.').css('color', 'red');
				empNoValid = false;
			}
		} else { // 사원번호 미입력 시
			$('#empNoMsg').text('사원번호를 입력해주세요.').css('color', 'red');
			empNoValid = false;
		}
	}


part4

4.1. 공백검사
	$('#addMemberBtn').click(function() {
    // 공백검사
    
	});

버튼 클릭시 공백검사를 진행하고, 주소값을 합쳐 폼을 제출하려고 했으나
기능별로 코드를 묶기 위해 공백검사 및 클릭시 이벤트 발생하는 함수를 분리.

4.2. 공백검사 version_2
		function validateInputs() {
			let isValid = true;
			
			// 각 input 입력값 가져오기
			let empNo = $('#empNo').val();
			let pw1 = $('#pw1').val();
			let pw2 = $('#pw2').val();
			let gender = $('input[name="gender"]:checked').val();
			let email = $('#email').val();
			let address = $('#sample6_address').val();
			let detailAddress = $('#sample6_detailAddress').val();
		
			// 각 입력값 검사하기
			if (empNo == '') {
				alert('사원번호를 입력하세요.');
				isValid = false;
			}
			// 사원번호 비동기 검사는 이미 진행
			if (!empNoValid) { 
				alert('사원번호를 확인하세요.');
				isValid = false;
			}
			// 비밀번호 정규식 검사 및 비밀번호 일치여부 검사는 이미 진행
			if (pw1 == '') {
				alert('비밀번호를 입력하세요.');
				isValid = false;
			}
			if (pw2 == '') {
				alert('비밀번호 확인을 입력하세요.');
				isValid = false;
			}
			if (gender == undefined) {
				alert('성별을 선택하세요.');
				isValid = false;
			}
			if (email == '') {
				alert('이메일을 입력하세요.');
				isValid = false;
			}
			if (address == '' || detailAddress == '') {
				alert('주소를 입력하세요.');
				isValid = false;
			}
		
			return isValid;
		}

part5

5.1. 회원가입 버튼 클릭 시 이벤트 발생 version_1
$('#addMemberBtn').click(function() {
    // 공백검사
    
    // 주소값 가져오기
	let postcode = $('#sample6_postcode').val();
	let address = $('#sample6_address').val();
	let detailAddress = $('#sample6_detailAddress').val();
    
    // 한줄의 주소로 합치기
	let fullAddress = postcode + " " + address + " " + detailAddress;
	
    console.log('주소 : ' + fullAddress);
    // hidden input에 fullAddress 값 저장
	$('#fullAddress').val(fullAddress);
    
});

part4 설명 참고.

  • 이전 코드에서는 사원번호 확인 관련 비동기 함수에서만 페이지 로딩을 했는데, 이벤트가 주어지는 모든 함수에 대해 페이지 로드를 적용
  • $(function(){}) 가능.
5.2. 회원가입 버튼 클릭 시 이벤트 발생 version_2

-사원번호 비동기 검사 함수의 성공/실패 여부 + 비밀번호 정규식 검사 함수의 성공/실패 여부 + 공백 검사의 성공/실패 여부 확인 후 폼 제출/미제출 결정.
-커서를 뗄 때 발생하는 이벤트를 모음.

// 이벤트 스크립트 시작
		$(document).ready(function() {
			// 페이지 로드 시 사원번호 검사를 최조 1번 실행
			checkEmpNo();
			
			// 회원가입 실패시 alert
			let error = '${param.error}'; // 회원가입 실패시 url에 매개값 error=true 전달
			if (error == 'true') { // error의 값이 true이면
			    console.log('회원가입 실패');
			    alert('회원가입에 실패했습니다. 다시 시도해주세요.');
			}
			
			// 사원번호 입력 후 커서를 떼면 이벤트 발생
			$('#empNo').blur(function() {
				checkEmpNo(); // 사원번호 비동기 검사 함수 호출
			});

			// 비밀번호 입력 후 커서를 떼면 이벤트 발생
			$('#pw1').blur(function() { 
				validatePassword(); // 정규식 검사 함수 호출
				checkPasswordMatch(); // 일치불일치 검사 함수 호출
			});
			
			// 비밀번호 확인란 입력 후 커서를 떼면 이벤트 발생
			$('#pw2').blur(function() { 
				checkPasswordMatch(); // 일치불일치 검사 함수 호출
			});

			// 회원가입 버튼 클릭 시
			$('#addMemberBtn').click(function(event) {
		    	// 1) 주소값 가져오기
				let postcode = $('#sample6_postcode').val(); // 우편번호
				let address = $('#sample6_address').val(); // 주소
				let detailAddress = $('#sample6_detailAddress').val(); // 상세주소
				// 한줄의 주소로 합치기
				let fullAddress = postcode + " " + address + " " + detailAddress;
				console.log('주소 : ' + fullAddress);
				// hidden input에 주소값 저장
				$('#fullAddress').val(fullAddress);
				
				// 2) 유효성 및 공백 검사
				let allFieldsValid = empNoValid && validatePassword() && checkPasswordMatch() && validateInputs(); // 사원번호 비동기 검사 함수의 성공/실패 여부 + 비밀번호 정규식 검사 함수의 성공/실패 여부 + 공백 검사의 성공/실패 여부
		
				if (allFieldsValid) {
					$('form').submit(); // 폼 제출
				} else {
					alert('사원번호 또는 비밀번호를 확인해주세요.');
					event.preventDefault(); // 폼 제출 막기
				}
			});

			// 취소 버튼 클릭 시
			$('#cancelBtn').click(function() {
				let result = confirm('로그인 페이지로 이동할까요?'); // 사용자 선택 값에 따라 true or false 반환
				if (result) {
					window.location.href = '/login'; // 로그인 페이지로 이동
				}
			});
		});

6 view

jsp 전체
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>addMember</title>
	<!-- JQuery -->
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.0/jquery.min.js"></script>
	<!-- 다음 카카오 도로명 주소 API 사용 -->
	<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
	<script>
		// 함수 선언 시작
		// 도로명 주소 찾기 함수
		function sample6_execDaumPostcode() {
			new daum.Postcode({
				oncomplete: function(data) {
					// 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.
					// 각 주소의 노출 규칙에 따라 주소를 조합한다.
					// 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
					var addr = ''; // 주소 변수
					var extraAddr = ''; // 참고항목 변수
		
					// 사용자가 선택한 주소 타입에 따라 해당 주소 값을 가져온다.
					if (data.userSelectedType == 'R') { // 사용자가 도로명 주소를 선택했을 경우
						addr = data.roadAddress;
					} else { // 사용자가 지번 주소를 선택했을 경우(J)
						addr = data.jibunAddress;
					}
		
					// 사용자가 선택한 주소가 도로명 타입일때 참고항목을 조합한다.
					if (data.userSelectedType == 'R') {
						// 법정동명이 있을 경우 추가한다. (법정리는 제외)
						// 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
						if (data.bname != '' && /[동|로|가]$/g.test(data.bname)) {
							extraAddr += data.bname;
						}
						// 건물명이 있고, 공동주택일 경우 추가한다.
						if (data.buildingName != '' && data.apartment == 'Y') {
							extraAddr += (extraAddr != '' ? ', ' + data.buildingName : data.buildingName);
						}
						// 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
						if (extraAddr != '') {
							extraAddr = ' (' + extraAddr + ')';
						}
						// 조합된 참고항목을 해당 필드에 넣는다.
						$('#sample6_extraAddress').val(extraAddr);
					} else {
						$('#sample6_extraAddress').val('');
					}
		
					// 우편번호와 주소 정보를 해당 필드에 넣는다.
					$('#sample6_postcode').val(data.zonecode);
					$('#sample6_address').val(addr);
					// 커서를 상세주소 필드로 이동한다.
					$('#sample6_detailAddress').focus();
				}
			}).open();
		}
	
		// 비밀번호 정규식 검사 함수
		function validatePassword() {
			// 정규식 패턴은 양 끝에 슬래시를 포함해야 한다
			let pwPattern = /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[!@#$%^&*()_+{}:;<>,.?~[\]\-]).{8,}$/;
			let pw1 = $('#pw1').val();
			let successMsg = '사용 가능한 비밀번호입니다.';
			let errorMsg = '최소 8자 이상, 영문 대소문자, 숫자, 특수문자를 포함해주세요.';
			
			if ( pwPattern.test(pw1) ) { // test 메서드는 해당 문자열이 정규식과 패턴이 일치하면 true를 반환
				$('#pwMsg1').text(successMsg).css('color', 'green');
				console.log('비밀번호 정규식 일치');
				return true;
			} else {
				$('#pwMsg1').text(errorMsg).css('color', 'red');
				console.log('비밀번호 정규식 불일치');
				return false;
			}
		}
		
		// 비밀번호 일치불일치 검사 함수
		function checkPasswordMatch() {
			let pw1 = $('#pw1').val();
			let pw2 = $('#pw2').val();
			let successMsg = '비밀번호가 일치합니다.';
			let errorMsg = '비밀번호가 일치하지 않습니다.';
			
			if ( pw1 == pw2 ) { 
				$('#pwMsg2').text(successMsg).css('color', 'green');
				console.log('비밀번호 일치');
				return true;
			} else { 
				$('#pwMsg2').text(errorMsg).css('color', 'red');
				console.log('비밀번호 불일치')
				return false;
			}
		}
		
		// 사원번호 비동기 검사 함수
		let empNoValid = false; // 사원번호 검사 결과 변수 선언
		
		function checkEmpNo() {
			let empNo = $('#empNo').val();
			
			if ( empNo != '' ) { // 사원번호가 입력되어 있을 시
				if ( empNo.length < 11 ) { // Integer 타입의 최대 정수 범위 검사
					// 비동기 검사 실행
					$.ajax({
						url : '/checkEmpNo',
						type : 'post',
						data : {empNo : empNo},
						success : function(response) {
							console.log('사원번호 검사 실행');
							
							// 검사 결과에 따라 분기
							if (response.empInfoCnt == 0 || response.memberInfoCnt != 0) {
								$('#empNoMsg').text(response.resultMsg).css('color', 'red'); // 반환된 메세지를 출력
								console.log('사원번호 검사 결과 -> 가입 불가능');
								empNoValid = false;
							} else {
								$('#empNoMsg').text(response.resultMsg).css('color', 'green'); // 반환된 메세지를 출력
								console.log('사원번호 검사 결과 -> 가입 가능');
								empNoValid = true;
							}
						},
						error: function(error) {
		                	console.error('사원번호 검사 실패: ' + error);
		                	empNoValid = false;
		                }
					});
				} else { // 사원번호를 11자리 이상 입력할 경우
					$('#empNoMsg').text('사원번호는 7자리입니다.').css('color', 'red');
					empNoValid = false;
				}
			} else { // 사원번호 미입력 시
				$('#empNoMsg').text('사원번호를 입력해주세요.').css('color', 'red');
				empNoValid = false;
			}
		}
		
		// 공백 검사 함수
		function validateInputs() {
			let isValid = true;
			
			// 각 input 입력값 가져오기
			let empNo = $('#empNo').val();
			let pw1 = $('#pw1').val();
			let pw2 = $('#pw2').val();
			let gender = $('input[name="gender"]:checked').val();
			let email = $('#email').val();
			let postcode = $('sample6_postcode').val();
			let address = $('#sample6_address').val();
			let detailAddress = $('#sample6_detailAddress').val();
		
			// 각 입력값 검사시작
			// 사원번호 비동기 검사는 이미 진행
			if (empNo == '') {
				alert('사원번호를 입력하세요.');
				isValid = false;
				return isValid;
			}
			// 비밀번호 정규식 검사 및 비밀번호 일치여부 검사는 이미 진행
			if (pw1 == '') {
				alert('비밀번호를 입력하세요.');
				isValid = false;
				return isValid;
			}
			if (pw2 == '') {
				alert('비밀번호 확인을 입력하세요.');
				isValid = false;
				return isValid;
			}
			if (gender == undefined) {
				alert('성별을 선택하세요.');
				isValid = false;
				return isValid;
			}
			if (email == '') {
				alert('이메일을 입력하세요.');
				isValid = false;
				return isValid;
			}
			if (postcode == '' || address == '' || detailAddress == '') {
				alert('주소를 입력하세요.');
				isValid = false;
				return isValid;
			}
		
			return isValid;
		}

		// 이벤트 스크립트 시작
		$(document).ready(function() {
			// 페이지 로드 시 사원번호 검사를 최초 1번 실행
			checkEmpNo();
			
			// 회원가입 실패시 alert
			let result = '${param.result}'; // 회원가입 실패시 url의 매개값으로 result=fail 전달
			if (result == 'fail') { // result의 값이 fail이면
			    console.log('회원가입 실패');
			    alert('회원가입에 실패했습니다. 다시 시도해주세요.');
			}
			
			// 사원번호 입력 후 커서를 떼면 이벤트 발생
			$('#empNo').blur(function() {
				checkEmpNo(); // 사원번호 비동기 검사 함수 호출
			});

			// 비밀번호 입력 후 커서를 떼면 이벤트 발생
			$('#pw1').blur(function() { 
				validatePassword(); // 정규식 검사 함수 호출
				checkPasswordMatch(); // 일치불일치 검사 함수 호출
			});
			
			// 비밀번호 확인란 입력 후 커서를 떼면 이벤트 발생
			$('#pw2').blur(function() { 
				checkPasswordMatch(); // 일치불일치 검사 함수 호출
			});

			// 회원가입 버튼 클릭 시
			$('#saveBtn').click(function(event) {
		    	// 1) 주소값 가져오기
				let postcode = $('#sample6_postcode').val(); // 우편번호
				let address = $('#sample6_address').val(); // 주소
				let detailAddress = $('#sample6_detailAddress').val(); // 상세주소
				// 한줄의 주소로 합치기
				let fullAddress = postcode + ' ' + address + ' ' + detailAddress;
				console.log('주소 : ' + fullAddress);
				// hidden input에 주소값 저장
				$('#fullAddress').val(fullAddress);
				
				// 2) 유효성 및 공백 검사
				let allFieldsValid = empNoValid && validatePassword() && checkPasswordMatch() && validateInputs();	
		
				if (allFieldsValid) { // 모든 항목이 유효하면
					$('form').submit(); // 폼 제출
				} else if (!empNoValid) { // 사원번호 검사가 false이면
					alert('사원번호를 확인해주세요.');
					event.preventDefault(); // 폼 제출 막기
				} else if ( !validatePassword() || !checkPasswordMatch() ) { // 비밀번호 검사가 false이면
					alert('비밀번호를 확인해주세요.');
					event.preventDefault(); // 폼 제출 막기
				} else { // !validateInputs() // 공백 검사가 false이면
					event.preventDefault(); // 폼 제출 막기
				}
			});

			// 취소 버튼 클릭 시
			$('#cancelBtn').click(function() {
				let result = confirm('로그인 페이지로 이동할까요?'); // 사용자 선택 값에 따라 true or false 반환
				if (result) {
					window.location.href = '/login'; // 로그인 페이지로 이동
				}
			});
		});
	</script>
</head>
<body>
	<form action="/member/addMember" method="post">
		<table border="1">
			<tr>
				<td colspan="3">
					<h1>회원가입</h1>
				</td>
			</tr>
			<tr>
				<td>사원번호</td>
				<td>
					<input type="number" name="empNo" value="${empNo}" id="empNo"> <!-- empNo가 넘어올경우 출력 -->
				</td>
				<td>
					<span id="empNoMsg"></span>
				</td>
			</tr>
			<tr>
				<td>비밀번호</td>
				<td>
					<input type="password" name="pw" placeholder="비밀번호를 입력하세요" id="pw1">
				</td>
				<td>
					<span id="pwMsg1">최소 8자 이상, 영문 대소문자, 숫자, 특수문자를 포함해주세요.</span>
				</td>
			</tr>
			<tr>
				<td>비밀번호 확인</td>
				<td>
					<input type="password" name="pw2" placeholder="비밀번호를 한번 더 입력하세요" id="pw2">
				</td>
				<td>
					<span id="pwMsg2"></span>
				</td>
			</tr>
			<tr>
				<td>성별</td>
					<td colspan="2">
					<input type="radio" name="gender" value="M"><input type="radio" name="gender" value="F"></td>
			</tr>
			<tr>
				<td>이메일</td>
				<td>
					<input type="email" name="email" id="email">
				</td>
				<td>
					<span id="emailMsg"></span>
				</td>
			</tr>
			<tr>
				<td>주소</td>
				<td colspan="2">
					<!-- 도로명 주소 찾기 input -->
					<input type="text" id="sample6_postcode" placeholder="우편번호">
					<input type="button" onclick="sample6_execDaumPostcode()" value="우편번호 찾기"><br>
					<input type="text" id="sample6_address" placeholder="주소"><br>
					<input type="text" id="sample6_detailAddress" placeholder="상세주소">
					<input type="text" id="sample6_extraAddress" placeholder="참고항목">
					<input type="hidden" name="address" id="fullAddress">
				</td>
			</tr>
		</table>
		<button type="button" id="cancelBtn">취소</button> <!-- 왼쪽 정렬 -->
		<button type="submit" id="saveBtn">저장</button> <!-- 오른쪽 정렬 -->
	</form>
</body>
</html>

사원명은 제외
제외 사유: 사원명은 member와 emp 테이블에서 관리했었음.
그런데 만약 동명이인의 사원이 존재할 경우, 어떠한 처리를 거쳐 emp 테이블에서는 홍길동a, 홍길동b... 와 같이 순서를 붙여 관리해야한다는 번거로움이 존재. 이로 인해 emp 인사 테이블에서 emp_name만 관리하기로 결정.

part7

MemberController
package com.fit.controller;

import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.fit.CC;
import com.fit.service.MemberService;
import com.fit.vo.MemberInfo;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Controller
public class MemberController {
	@Autowired
	private MemberService memberService;
	
	// 회원가입 폼
	@GetMapping("/member/addMember")
	public String addMember(HttpSession session,
							@RequestParam(required = false, name = "empNo") Integer empNo,
							Model model) {
		// 로그인 상태면 home으로 분기 -> 앞으로는 안받아와도 된다 인터셉터에서 처리한다
		if(session.getAttribute("loginMemberId") != null) {
			log.debug(CC.HE + "MemberController.addMember() loginMemberId : " + session.getAttribute("loginMemberId") + CC.RESET);
			return "/home";
		}
		
		// 매개값 empNo가 넘어오면 view에서 출력한다
		if(empNo != null) {
			log.debug(CC.HE + "MemberController.addMember() empNo param : " + empNo + CC.RESET);
			model.addAttribute("empNo", empNo);
		}
		
		return "/member/addMember";
	}
	
	// 회원가입 액션
	@PostMapping("/member/addMember")
	public String addMember(MemberInfo memberInfo) {
		int row = memberService.addMember(memberInfo); // 회원가입 결과값
		
		if (row == 1) {
			log.debug(CC.HE + "MemberController.addMember() row : " + row + CC.RESET);
	        return "redirect:/login"; // 회원가입 성공 시 로그인 페이지로
	    } else { // 회원가입 실패 시
	    	log.debug(CC.HE + "MemberController.addMember() row : " + row + CC.RESET);
	        return "redirect:/member/addMember?result=fail";
	    }
	}
}

part8

MemberService
package com.fit.service;

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fit.CC;
import com.fit.mapper.MemberMapper;
import com.fit.vo.MemberInfo;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@Transactional
public class MemberService {
	@Autowired
	private MemberMapper memberMapper;
	
	// 사원번호 검사
	public Map<String, Object> checkEmpNo(int empNo) {
		// 1) 인사정보 등록여부 검사
		int empInfoCnt = memberMapper.empInfoCnt(empNo);
		log.debug(CC.HE + "MemberService.addMember() empInfoCnt : " + empInfoCnt + CC.RESET);
		
		// 2) 사원번호 중복검사
		int memberInfoCnt = memberMapper.memberInfoCnt(empNo);
		log.debug(CC.HE + "MemberService.addMember() memberInfoCnt : " + memberInfoCnt + CC.RESET);
		
		Map<String, Object> checkEmpNoResult = new HashMap<String, Object>();
		checkEmpNoResult.put("empInfoCnt", empInfoCnt);
		checkEmpNoResult.put("memberInfoCnt", memberInfoCnt);
		
		return checkEmpNoResult;
	}
	
	// 회원가입
	public int addMember(MemberInfo memberInfo) {
		int row = memberMapper.addMember(memberInfo);
		log.debug(CC.HE + "MemberService.addMember() row : " + row + CC.RESET);
		
		return row;
	}
}

part8

MemberMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.fit.mapper.MemberMapper">
	<!-- 인사정보 등록여부 검사 -->
	<select id="empInfoCnt" parameterType="int" resultType="int">
		SELECT
			COUNT(*)
		FROM
			emp_info
		WHERE
			emp_no = #{empNo}
	</select>
	
	<!-- 사원번호 중복검사 -->
	<select id="memberInfoCnt" parameterType="int" resultType="int">
		SELECT
			COUNT(*)
		FROM
			member_info
		WHERE
			emp_no = #{empNo}
	</select>
	
	<!-- 회원가입 -->
	<insert id="addMember" parameterType="com.fit.vo.MemberInfo">
		INSERT INTO member_info(
			emp_no,
			pw,
			gender,
			email,
			address,
			createdate,
			updatedate
		) VALUES (
			#{empNo},
			PASSWORD( #{pw} ),
			#{gender},
			#{email},
			#{address},
			NOW(),
			NOW()
		)
	</insert>
	
	<!-- 개인정보 조회 -->
	<select id="selectMemberInfo" parameterType="int" resultType="com.fit.vo.MemberInfo">
		SELECT
			emp_no empNo,
			gender,
			email,
			address,
			createdate,
			updatedate
		FROM
			member_info
		WHERE
			emp_no = ${empNo}
	</select>
	
	<!-- 개인정보 파일 조회 -->
	<select id="selectMemberFile" parameterType="java.util.Map" resultType="com.fit.vo.MemberFile">
		SELECT
			member_file_no memberFileNo,
			emp_no empNo,
			file_category fileCategory,
			member_ori_file_name memberOriFileName,
			member_save_file_name memberSaveFileName,
			member_filetype memberFiletype,
			member_path memberPath,
			createdate,
			updatedate
		FROM
			member_file
		WHERE
			emp_no = #{empNo}
		AND
			file_category = #{fileCategory}
	</select>
</mapper>

part9

MemberMapper
package com.fit.mapper;

import org.apache.ibatis.annotations.Mapper;

import com.fit.vo.MemberFile;
import com.fit.vo.MemberInfo;

@Mapper
public interface MemberMapper {
	// 인사정보 등록여부 검사
	int empInfoCnt(int empNo);
		
	// 사원번호 중복검사
	int memberInfoCnt(int empNo);
	
	// 회원가입
	int addMember(MemberInfo memberInfo);
	
	// 개인정보 조회
	MemberInfo selectMemberInfo(int empNo);
	
	// 개인정보 파일 조회
	MemberFile selectMemberFile(int empNo, String fileCategory);
}

오류

  • 변수명을 잘못입력하여 실행되지 않음
    //주소값 가져오기 ( sample3 -> sample6 )
    let postcode = $('#sample6_postcode').val();
    let address = $('#sample6_address').val();

1개의 댓글

comment-user-thumbnail
2023년 8월 16일

좋은 정보 얻어갑니다, 감사합니다.

답글 달기