My Project/도서 관리 프로그램 (final project)

5일차 - 회원가입 주소 api 연결, 유효성 및 정규화

미로910 2024. 9. 4. 19:33
1. 주소 api 연결
2. 회원가입 유효성 검사, 정규화 // 비밀번호 실시간 확인
3. 로그인 jsp 틀 잡기 
address.js -> 주소 api
  // 우편번호 찾기 찾기 화면을 넣을 element
  var element_wrap = document.getElementById('wrap');

  function foldDaumPostcode() {
    // iframe을 넣은 element를 안보이게 한다.
    element_wrap.style.display = 'none';
}

function execPostCode() {
    var currentScroll = Math.max(document.body.scrollTop, document.documentElement.scrollTop);
    new daum.Postcode({
        oncomplete: function(data) {
           // 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.

           // 도로명 주소의 노출 규칙에 따라 주소를 조합한다.
           // 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
            var roadAddr = data.roadAddress; // 도로명 주소 변수
            var extraRoadAddr = ''; // 도로명 조합형 주소 변수 (참고 항목)


    //사용자가 선택한 주소 타입에 따라 해당 주소 값을 가져온다.
    if (data.userSelectedType === 'R') { // 사용자가 도로명 주소를 선택했을 경우
        roadAddr = data.roadAddress;
    } else { // 사용자가 지번 주소를 선택했을 경우(J)
        roadAddr = data.jibunAddress;
    }



           // 법정동명이 있을 경우 추가한다. (법정리는 제외)
           // 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
           if(data.bname !== '' && /[동|로|가]$/g.test(data.bname)){
               extraRoadAddr += data.bname;
           }
           // 건물명이 있고, 공동주택일 경우 추가한다.
           if(data.buildingName !== '' && data.apartment === 'Y'){
              extraRoadAddr += (extraRoadAddr !== '' ? ', ' + data.buildingName : data.buildingName);
           }
           // 도로명, 지번 조합형 주소가 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
           if(extraRoadAddr !== ''){
               extraRoadAddr = ' (' + extraRoadAddr + ')';
           }
           // 도로명, 지번 주소의 유무에 따라 해당 조합형 주소를 추가한다.
           if(roadAddr !== ''){
            roadAddr += extraRoadAddr;
           }
             // 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
             if(extraRoadAddr !== ''){
                extraRoadAddr = ' (' + extraRoadAddr + ')';
            }

        // 우편번호와 주소 정보를 해당 필드에 넣는다.
        document.getElementById('zip').value = data.zonecode;
        document.getElementById("addr1").value = roadAddr;
        // document.getElementById("addr1").value = data.jibunAddress;

        document.getElementById("addr2").focus();
           
  

           
           /* document.getElementById('signUpUserPostNo').value = data.zonecode; //5자리 새우편번호 사용
           document.getElementById('signUpUserCompanyAddress').value = fullRoadAddr;
           document.getElementById('signUpUserCompanyAddressDetail').value = data.jibunAddress; */
       }
    }).open();
}
signUp.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>회원가입</title>

<script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
<link rel="stylesheet" href="/css/signUp.css" type="text/css" />
</head>
<body>


	<div class="signup-container">
		<h2>회원가입</h2>

		<form action="/user/sign-up" method="post">
			<div class="form-group">
				<label for="loginId">아이디</label> <input style="width: 81%"
					type="text" class="loginId" placeholder="아이디 입력" id="loginId"
					name="loginId" maxlength="12" required />

				<button type="button" class="check-id" id="check-id">중복체크</button>
				<p class="result-uid"></p>
			</div>
			
			<div class="form-group">
				<label for="password">비밀번호</label> <input type="password"
					class="form-control" placeholder="비밀번호 입력" id="password"
					name="password" required />
					<p class="result-upw"></p>

			</div>

			<div class="form-group">
				<label for="pwcheck">비밀번호 확인</label> <input type="password"
					class="form-control" placeholder="비밀번호 재입력" id="pwcheck"
					name="pwcheck"  required />
				<p class="result-pw"></p>
			</div>

			<div class="form-group">
				<label for="name">이름</label> <input type="text" class="form-control"
					placeholder=" 이름을 입력해주세요" id="name" name="name" required />
			</div>
			<br />
			<div class="form-group2">
				<label for="phone">전화번호 </label>

				<div class="phone">
					<select name="phone1">
						<option>010</option>
						<option>02</option>
						<option>031</option>
						<option>051</option>
					</select> - <input type="text" name="phone2" size="5" required maxlength="4" />
					- <input type="text" name="phone3" size="5" required maxlength="4" />
				</div>
			</div>


			<!-- 생년월일 입력 필드 추가 -->
			<div class="form-group2">
				<label for="birthDate">생년월일:</label>
				<div class="birthDate">
					<select name="year" required>
						<option>년도</option>
						<%
						for (int i = 1900; i <= 2024; i++) {
						%>
						<option value="<%=i%>"><%=i%></option>
						<%
						}
						%>
					</select> <select name="month" required style="margin: 5px">
						<option>월</option>
						<%
						for (int i = 1; i <= 12; i++) {
						%>
						<option value="<%=i%>"><%=i%></option>
						<%
						}
						%>
					</select><select name="day" required style="margin: 5px">
						<option>일</option>
						<%
						for (int i = 1; i <= 31; i++) {
						%>
						<option value="<%=i%>"><%=i%></option>
						<%
						}
						%>
					</select>
				</div>
			</div>



			<br />
		
			<div class="form-group">
			<label for="zip">주소:</label>
			
					<input type="text" id="zip" style="width: 79%;" placeholder="우편번호" name="zip" readonly="readonly">
					 <button type="button" class="btn btn-default" style="width: 19%" onclick="execPostCode();"><i class="fa fa-search"></i> 우편번호 찾기</button>  
			<br>
				
			</div>
			<div class="form-group">
					<input class="form-control" style="top: 5px;" placeholder="도로명 주소" name="addr1" id="addr1" type="text" readonly="readonly" />
			</div>
			<div class="form-group">
					<input type="text" id="addr2" placeholder="상세주소" name="addr2" >
			</div>

			<br />
			<div class="form-group2">
				<label for="email">이메일:</label> <input type="text"
					class="form-control" placeholder=" email" id="email" name="email1"
					required /> <span id="email2" class="input-group-text">@</span> <select
					name="email2">
					<option value="naver.com">naver.com</option>
					<option value="gmail.com">gmail.com</option>
					<option value="nate.com">nate.com</option>
					<option value="hanmail.net">hanmail.net</option>
					<option value="daum.net">daum.net</option>
				</select>
			</div>

			<br /> <br /> <input class="check" type="radio" name="gender"
				value="false" checked />남자 <input class="check" type="radio"
				name="gender" value="true" />여자 <br /> <br /> <br />

			<div>
				<button type="submit" class="btn">회원가입</button>
			</div>
		</form>
	</div>
</body>
<script src="/js/signup.js"></script>
<script src="/js/address.js"></script>
</html>
signUp.js

▶️ 정규식 표현

아이디 - 6~12자 이상 영문 소문자 및 숫자만 가능

비밀번호 - 최소 8자 이상, 특수문자 포함

이름 - 한글 또는 영어로만 입력 가능

// 아이디 (유효성, 중복확인)
const resultUid = document.querySelector(".result-uid"); // 에러 메세지(아이디)
const btnId = document.querySelector(".check-id"); // 중복체크 버튼
const inputId = document.querySelector(".loginId"); // 아이디
const btnSubmit = document.getElementById("btn"); // 회원가입 버튼

const reUid=/^[a-z]+[a-z0-9]{5,12}$/;
btnId.addEventListener("click",function(){
  const inputId=loginId.value.trim();
  console.log(inputId);
  if(!reUid.test(inputId)){
    resultUid.textContent="아이디는 6-12자의 영문 소문자 및 숫자만 사용 가능합니다.";
    resultUid.style.color='red';
    return;
  }
  const url="/controller-user/check-userId?loginId="+encodeURIComponent(inputId);
  console.log("url",url);
  fetch(url).then((response)=>{
    if(!response.ok){
      throw new Error('Network response was not ok');
    }
    return response.json();
  }).then((isUse)=>{
    console.log("결과 확인",isUse);
    if(isUse){
      resultUid.textContent="사용 가능한 ID입니다.";
      resultUid.style.color='green';
    }else{
      resultUid.textContent="중복된 ID입니다";
      resultUid.style.color='red';
      return;
    }
  }).catch((error)=>{
    console.error("에러 발생",error);
    resultUid.textContent="잘못된 요청입니다.";
    resultUid.style.color='red';
  });
});

  

// 비밀번호 체크 (유효성 검사, 비밀번호 확인)
document.addEventListener('DOMContentLoaded', function () {
  const passwordInput = document.getElementById('password');
  const confirmPasswordInput = document.getElementById('pwcheck');
  const passwordCheckMessage = document.querySelector('.result-upw');
  const confirmPasswordCheckMessage = document.querySelector('.result-pw');

  // 비밀번호 정규식 (최소 8자 이상, 특수문자 포함)
  const passwordRegex = /^(?=.*[\W_]).{8,}$/;

  function validatePasswordStrength(password) {
      if (password.length === 0) {
          return '';
      }

      if (!passwordRegex.test(password)) {
          return '비밀번호는 최소 8자 이상이어야 하며, 특수문자를 포함해야 합니다.';
      }

      return '비밀번호가 유효합니다.';
  }

  function checkPasswordsMatch() {
      const password = passwordInput.value;
      const confirmPassword = confirmPasswordInput.value;
      const strengthMessage = validatePasswordStrength(password);

      if (strengthMessage !== '비밀번호가 유효합니다.') {
          passwordCheckMessage.textContent = strengthMessage;
          passwordCheckMessage.style.color = 'red';
          passwordInput.style.borderColor = 'red';
          confirmPasswordInput.style.borderColor = '';
          return;
      } else {
          passwordCheckMessage.textContent = strengthMessage;
          passwordCheckMessage.style.color = 'green';
          passwordInput.style.borderColor = 'green';
      }

      if (confirmPassword === '') {
          confirmPasswordCheckMessage.textContent = '';
          confirmPasswordInput.style.borderColor = '';
          return;
      }

      if (password !== confirmPassword) {
          confirmPasswordCheckMessage.textContent = '비밀번호가 일치하지 않습니다.';
          confirmPasswordCheckMessage.style.color = 'red';
          confirmPasswordInput.style.borderColor = 'red';
      } else {
          confirmPasswordCheckMessage.textContent = '비밀번호가 일치합니다.';
          confirmPasswordCheckMessage.style.color = 'green';
          confirmPasswordInput.style.borderColor = 'green';
      }
  }

  passwordInput.addEventListener('input', checkPasswordsMatch);
  confirmPasswordInput.addEventListener('input', checkPasswordsMatch);
});


// 유효성 검사 (이름, 번호, 생년월일, 주소)
document.addEventListener("DOMContentLoaded", function () {
  const form = document.querySelector("form");

  form.addEventListener("submit", function (event) {
      // Name validation
      const name = document.getElementById("name").value.trim();
      const nameRegex = /^[가-힣a-zA-Z]+$/; // 이름 정규식
      if (!name) {
          alert("이름을 입력해주세요.");
          event.preventDefault();
          return;
      }
      if(!nameRegex.test(name)){
        alert("이름은 한글 또는 영어로만 입력 가능합니다.");
        event.preventDefault();
        return;
      }

      // Phone number validation
      const phone2 = document.querySelector("input[name='phone2']").value.trim();
      const phone3 = document.querySelector("input[name='phone3']").value.trim();
      if (!phone2 || !/^\d{4}$/.test(phone2)) {
          alert("유효한 전화번호를 입력해주세요.");
          event.preventDefault();
          return;
      }
      if (!phone3 || !/^\d{4}$/.test(phone3)) {
          alert("유효한 전화번호를 입력해주세요.");
          event.preventDefault();
          return;
      }

      // Birthdate validation
      const year = document.querySelector("select[name='year']").value;
      const month = document.querySelector("select[name='month']").value;
      const day = document.querySelector("select[name='day']").value;
      if (year === "년도" || month === "월" || day === "일") {
          alert("생년월일을 올바르게 입력해주세요.");
          event.preventDefault();
          return;
      }

      // Address validation
      const zip = document.getElementById("zip").value.trim();
      const addr1 = document.getElementById("addr1").value.trim();
      if (!zip || !addr1) {
          alert("주소를 입력해주세요.");
          event.preventDefault();
          return;
      }

      // Email validation
      const email1 = document.getElementById("email").value.trim();
      const email2 = document.querySelector("select[name='email2']").value;
      if (!email1 || !validateEmail(email1 + "@" + email2)) {
          alert("유효한 이메일을 입력해주세요.");
          event.preventDefault();
          return;
      }
  });

  // Email validation helper function
  function validateEmail(email) {
      const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      return re.test(email);
  }
});

 

로그인

signIn.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ include file="../layout/header.jsp"%>
    <meta charset="UTF-8">
    <title>로그인</title>
    <link rel="stylesheet" href="/css/signIn.css" type="text/css" />


    <main class="container_wrapper">
        <section class="contents_wrap login">
            <div class="login_form_wrap">
				<form action="/user/sign-in" method = "post">

                <!-- 로그인 -->
                <div class="form_col_group valid_check">
                    <div class="col_box id">
                        <input type="text" title="아이디 입력" class="form_ip" id="loginId" name="loginId" placeholder="아이디를 입력해 주세요." >
                        <!-- 아이디 상태값 -->
                        <span class="form_desc tip"></span>
                    </div>
                    <div class="col_box pw">
                        <div class="form_ip_pw">
                            <input type="password" class="form_ip" id="password" name="password" placeholder="비밀번호를 입력해 주세요." title="비밀번호 입력">
                         
                        </div>
                    </div>
                    <!-- 로그인 페이지의 경고 문구는 모두 여기에 표시됩니다.  -->
                    <span class="valid_desc"></span>
                </div>
                <!-- // 로그인 -->

                <div class="btn_wrap justify">
                    <button class="btn_lg btn_light_gray" type="submit" id="loginBtn" >
                       로그인
                    </button>
                </div>
                </form>

                <!-- 아이디 저장 -->
                <div class="save_id_box">
                    <span class="form_chk">
                        <input id="formSaveId" type="checkbox" >
                        <label for="formSaveId">아이디 저장</label>
                    </span>
                    <div class="right_area">
                        <a href="#"><span class="text btn_text_id_link">아이디 찾기</span></a>
                        <span class="gap">|</span>
                        <a href="#"><span class="text btn_text_pw_link">비밀번호 찾기</span></a>
                    </div>
                </div>
                <!-- // 아이디 저장 -->

                <!-- SNS 로그인 -->
                <div class="sns_login_box">
                    <ul class="sns_login_list">
                        <li class="sns_login">
                            <button class="btn_sns_login naver">
                                <span class="hidden">네이버로그인</span>
                            </button>
                        </li>
                        <li class="sns_login">
                            <button class="btn_sns_login kakao">
                                <span class="hidden">카카오로그인</span>
                            </button>
                        </li>
                        <li class="sns_login">
                        <div class="btn_sns_login google" >
                            <a href="https://accounts.google.com/o/oauth2/v2/auth/oauthchooseaccount?client_id=202693057051-amq7bn7fcoblosijrvt32o1nnq1bt879.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Flogin%2Foauth2%2Fcode%2Fgoogle&response_type=code&scope=email%20profile&service=lso&o2v=2&ddm=1&flowName=GeneralOAuthFlow">
                            구글 로그인
                            </a>
                        </div>
                        </li>
                    </ul>
                </div>
                
    
                <!-- // SNS 로그인 -->

                <!-- 회원가입 -->
                <div class="btn_wrap justify">
                    <a href="/user/sign-up" class="btn_lg btn_line_primary" id="join">
                        <span class="text">회원가입</span>
                    </a>
                </div>
                <!-- // 회원가입 -->

            </div>
        </section>
    </main>
<%@ include file="../layout/footer.jsp"%>

 


⭐ 아이디 

⭐ 비밀번호

⭐ 이름 

⭐ 전화번호

⭐ 주소 api


✨ 회원가입

✨ 로그인