사이드 프로젝트 도전기

[Project] *사용자 사이트 구축* / PHP / 2. 회원가입

Developer D 2023. 6. 10. 17:59

2023.06.10 - [사이드 프로젝트 도전기] - [Project] *사용자 사이트 구축* / PHP / 1. 환경 구축 부터 로그인까지

 

[Project] *사용자 사이트 구축* / PHP / 1. 환경 구축 부터 로그인까지

한걸음부터 다시 시작하기 프로젝트! Project 라고 하기도 뭐하지만 회원가입부터 다시 시작해보는 글! 기술스택요약 사용언어 : PHP, HTML, SQL 데이터베이스 : mySQL 서버 : Apache 사용툴 및 환경 : 챗 GP

silver-liq9118.tistory.com

한걸음부터 다시 시작하기 프로젝트!

간단한 사용자 사이트를 서버부터 페이지까지 만들어보기

2. 회원가입

1. 환경구축 및 로그인편에서 이어집니다!


 

기술스택요약

  • 사용언어 : PHP, HTML, SQL
  • 데이터베이스 : mySQL
  • 서버 : Apache
  • 사용툴 및 환경 : 챗 GPT,  휴먼지능(본인), VsCode, XAMPP

프로젝트 요약 (회원가입)

- HTML을 통한 웹 기능 및 디자인

- PHP를 통한기능 구현 (데이터베이스 연결 및 HTML 입력값을 받아 데이터베이스에 추가하여 회원가입을 완료시킨다.)

구현 느낀점 요약

- 앞글에서도 언급했지만 회원가입은 내생각보다 더 까다로웠다.

- 버튼은 submit이 아니므로 동기화를 시켜줘야한다.

- 생각보다 경우의 수가 너무 다양해서 구현하기 힘들었다.

- HTML 에서 버튼은 Submit이 아니므로 버튼을 누를때마다 통신하려면 아작스를 이용해야한다.

- GPT에게 코드를 완전 맡기는 것 보다 기본틀을 제공받고 본인이 수정하는 게 좀더 빨랐다… → 이부분에서 굉장히 삽질했음. 😂💃 (쉬운길은없어..) 

 


기본적으로 로그인 페이지에서 회원가입 페이지를 누르면 연결하도록 하였다.

Login_page.html

 <a href="Join_page.html">회원가입</a>

경로를 연결할때는 항상 절대경로와 상대경로그리고 이름을 잘확인하여야 한다.

로그인 → 회원가입 (미리보기)

기능 및 디자인 정리

회원가입을 만들다가 요소를 추가하고 추가하고 추가하다 보니까 정리가 잘안되어서 내가 원하는 기능 이나 디자인을 부분을 정리해보기로 했다.

  1. 회원가입 양식은 필수 양식임.
  2. 사용자는 유효한 이메일 형식을 사용해야함.
    →  사용자는 이메일형식이 아닌 다른 형식을 사용할때 페이지를 넘어가지 않고 수정할 수 있도록 해야함.
  3. 기존에 데이터베이스에 있는 중복 ID를 사용할 수 없음 →  ID중복확인을 눌렀을때 사용자가 페이지를 넘어가지 않고 해당 화면에서 확인할 수 있어야함.
    → 버튼을 눌렀을 때 페이지가 이동되지 않고 통신으로 계속 값을 받아와야함.
  4. 유효한 이메일 형식을 사용하였더라도 Password와 Password Confirm 이 맞지않으면 가입이 안됨.
  5. Password ↔ Password Confirm이 일치하더라도 유효한 이메일(양식, 중복) 상태일때 ID를 다시 확인하라는 문구가 작성됨.
  6. 모든 필수 칸이 유효할 때 데이터베이스에 ID,PW 전송하여 회원가입완료!

페이지를 넘어가지않고 특정한 양식에 값을 검사해야한다는 부분이 조금 발목을잡았던 것 같다.

나는 해당 기능을 프로젝트 중간에 정리하여 지체했지만 앞으로는 조금더 자세히 명시하여 시작할 필요가 있는 것  같다.

 

 join_page.html

//Join.HTML
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>회원가입</title>
</style>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
  


  function clearDefaultValue(input) {
    if (input.value === input.defaultValue) {
      input.value = "";
    }
  }

  var duplicate_message = '';

  function id_duplication() {
  /* ID 중복 확인 버튼을 클릭했을 때 실행할 코드 */
  /* PHP 파일로부터 받은 응답을 처리하는 코드*/
  var email = document.getElementById("email").value;
  $.ajax({
    url: 'check_duplicate.php', // PHP 파일의 경로
    type: 'POST',
    dataType: 'html',
    data: {email:email}, // PHP 파일로 전달할 데이터
    success: function(response) {
      $('#duplicate_message').html(response); // 결과를 표시할 요소에 HTML 삽입
      duplicate_message = $('#duplicate_message').text();
      confirm_error();
    },
    error: function() {
      alert('오류가 발생했습니다.');
    }
  });

  }

  function confirm_error() {
  /* PHP 파일로부터 받은 응답을 처리하는 코드*/
  var password = document.getElementById("password").value;
  var password_confirm = document.getElementById("password_confirm").value;
  var ID_confirm = duplicate_message;

  // 특정 조건 확인
  if (password === "" | password_confirm === ""){
    $('#password_confirm_error').html("패스워드를 입력해주세요")
  
    }

    else {

      
    if (password === password_confirm) {
          $('#password_confirm_error').html("패스워드가 일치합니다.")
          if(duplicate_message==="사용 가능한 ID입니다."){  
            return true;
          }
          else {
            console.log(ID_confirm);
            $('#confirm_error').html("ID를 다시 확인해 주세요.");
            return false;
          }
          
        } else {
          // 조건 미충족 시 페이지 이동 중지
          $('#password_confirm_error').html("패스워드가 일치하지 않습니다.");
          return false;
        }

    
    
    }
}

</script>
  <style>
    /* 스타일링을 위한 CSS 코드 */
    body {
      font-family: Arial, sans-serif;
      height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      margin: 0;
    }
    .container {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      width: 400px;
      height: auto;
      border: 1px solid #ccc;
      background-color: #f4f4f4;
      padding: 20px;
    }
    h2 {
      text-align: center;
      font-size: 24px;
      margin-bottom: 20px;
    }

    input[type="text"]:focus,
    input[type="password"]:focus {
      /* 포커스 시 기본값 숨김 */
      background-color: white;
    }

    .form-group {
      margin-bottom: 20px;
      text-align: center;
    }
    .input-row {
      display: flex;
      align-items: center;
      margin-bottom: 10px;
    }
    .input-label {
      font-size: 18px;
      margin-right: 10px;
    }
    input[type="text"],
    input[type="password"] {
      flex: 1;
      padding: 10px;
      font-size: 16px;
      border: 1px solid #ccc;
      border-radius: 4px;
    }
    input[type="text"]:focus,
    input[type="password"]:focus {
      /* 포커스 시 기본값 숨김 */
      background-color: white;
    }
    input[type="submit"] {
      width: 100%;
      padding: 10px;
      background-color: #4CAF50;
      color: white;
      border: none;
      cursor: pointer;
      font-size: 18px;
    }
    .register-link {
      text-align: center;
      margin-top: 10px;
      font-size: 16px;
      color: #888;
    }
    .register-link a {
      text-decoration: none;
      color: #888;
    }
    .message {
      margin-top: 10px;
      font-size: 14px;
      color: #888;
    }
    .error-message {
      margin-top: 10px;
      font-size: 14px;
      color: red;
    }
    .custom-button {
      padding: 10px 20px;
      font-size: 16px;
      background-color: #4CAF50;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }
  </style>
</head>
<body>
  <div class="container">
    <h2>&#127939;Join US&#127939;</h2>
    <form action="join.php" method="post" onsubmit="return confirm_error()">
    <form action="check_duplicate.php" method="post"> 
      <div class="form-group">
        <!--ID 중복체크-->
        <div class="input-row">
          <label for="email" class="input-label">ID:</label>
          <input type="text" id="email" name="email" required
          onfocus="clearDefaultValue(this)" value="example@abc.com">
          <button type="button" onclick="id_duplication()"  class="custom-button">ID 중복 확인</button>
        </div>
        <div class="error-message"><p id="duplicate_message"></p></div>
        
        <!--회원가입-->
      <div class="form-group">
        <div class="input-row">
          <label for="password" class="input-label">Password:</label>
          <input type="password" id="password" name="password" required>
        </div>
        <div class="error-message"></div>
        <div class="input-row">
          <label for="password_confirm" class="input-label">Password Confirm:</label>
          <input type="password" id="password_confirm" name="password_confirm" required>
        </div>
        <div class="error-message"><p id="password_confirm_error"></p></div>
        <div class="error-message"><p id="confirm_error"></p></div>
      </div>
      <input type="submit" onclick="confirm_error()" value="회원가입" name="join">
    </form>
    </form>
  </div><p></p></div>
</body>
</html>

기본 화면  → ID를입력하면 placeholder 속성으로 예시값은 사라진다.

check_duplicate.php

이메일의 유효값을 검사하는 기능을 분리했다.

이메일 형식을 검사하며, 중복을 검사한다.

<?php
include "db_conn.php";

$email_pattern = '/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
  $email = $_POST['email'];

  // 중복 확인
  $sql = "SELECT email FROM users WHERE email='$email'";
  $result = $conn->query($sql);

if(preg_match($email_pattern, $email)){

    if ($email==="example@abc.com"){
        echo "예시 이메일은 사용하실 수 없습니다.<br>";
    }
    else if (mysqli_num_rows($result)) {
        echo "중복된 ID입니다.<br>"; 
    } else {
        echo "사용 가능한 ID입니다.<br>";
        $id_confirm = true;
    }
}
else {
    echo "유효하지 않은 이메일 주소입니다.";
}
 
}


?>

join.php

앞에 이메일 유혀성검사가  끝나고 패스워드 확인까지 마치면, 가입이 완료된다.

include "db_conn.php";

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    
    $password = $_POST['password'];
    $password_confirm = $_POST['password_confirm'];
    $email = $_POST['email'];
    $name = $_POST['name'];
    

    
    if($password === $password_confirm){

      
      $sql = "INSERT INTO users (email, password, username) VALUES ('$email', '$password', '$name')";
      $result = $conn->query($sql);

      echo "회원가입 되었습니다! <br>";
      echo "반갑습니다!".$email." 회원님";
   
    }
    
    else{
      echo "패스워드가 일치하지 않습니다.";
    }

   

   }

php를 통해 데이터베이스등 값을 주고받아 기능 구현

<핵심코드 해설>

ID 중복 확인 아작스를 통해서 버튼을 눌렀을 때 페이지가 이동되지 않고 HTML  PHP → DB  → HTML 통신을 해야함.

HTML에서 Script로 아작스를 통해 값을 받아 올 수 있도록 구성  → PHP 기능 분리를 통해 중복만 체크하는 PHP 생성 → DB 쿼리로 중복값체크 → 해당값을 아작스로 HTML 수신 

 

Join_page.html (중복확인 함수 만들기)

  function id_duplication() {
  /* ID 중복 확인 버튼을 클릭했을 때 실행할 코드 */
  /* PHP 파일로부터 받은 응답을 처리하는 코드*/
  var email = document.getElementById("email").value;
  $.ajax({
    url: 'check_duplicate.php', // PHP 파일의 경로
    type: 'POST',
    dataType: 'html',
    data: {email:email}, // PHP 파일로 전달할 데이터
    success: function(response) {
      $('#duplicate_message').html(response); // 결과를 표시할 요소에 HTML 삽입
      duplicate_message = $('#duplicate_message').text();
      receive();
    },
    error: function() {
      alert('오류가 발생했습니다.');
    }
  });
  }

버튼이 눌렀을때 email 값을 PHP로 보내 DB쿼리를 실행하고 다시 결과를 가져와서 HTML에 표현한다.

해당 ID가 중복된 ID인지, 사용가능한 ID인지 확인

 

Join_page.html(패스워드가 일치해도 ID가 유효하지 않으면 ID를 확인해야하는 함수 작성)

 function receive(){

  password = document.getElementById("password").value;
  password_confirm = document.getElementById("password_confirm").value;
  ID_confirm = duplicate_message;


  }

 
  function confirm_error() {
  
    receive()

  // 특정 조건 확인
  if (password === "" | password_confirm === ""){
    $('#password_confirm_error').html("패스워드를 입력해주세요")
  
    }

    else {

      
    if (password === password_confirm) {
          $('#password_confirm_error').html("패스워드가 일치합니다.")
          if(duplicate_message==="사용 가능한 ID입니다."){  
            return true;
          }
          else {
            console.log(ID_confirm);
            $('#confirm_error').html("ID를 다시 확인해 주세요.");
            return false;
          }
          
        } else {
          // 조건 미충족 시 페이지 이동 중지
          $('#password_confirm_error').html("패스워드가 일치하지 않습니다.");
          return false;
        }

    
    
    }
}

패스워드가 동일해도 ID유효성을 검사하고 회원가입을 완료해야 하기 때문에, 고민하다가 

먼저 유효성을 검사하고, 나오는 에러 메세지로 페이지를 이동하는 것으로 정했다.

 

사용자는 ID 중복검사를누르면 id_duplication()함수가 실행된다. id_duplication()실행시 recevie() 함수가 실행되게 되어

사용가능한 ID 인지, 중복된 ID인지  결과값을 저장하게된다.

이 값은 저장되고,

회원가입 버튼을 누르면 confirm_id()가 최종적으로 실행된다.

이 함수에서 최종적으로 패스워드와 패스워드 확인이 일치한지 검사하고, 두 비밀번호가 일치한다면 ID가 유효한지 검사한다.

 

*receive() 함수와 confirm_id()함수를 분리한 이유는 두 함수가 id_duplication()에서 실행되면 ID중복버튼을 누를때 패스워드도 동시에 검사하게 되는 사소한 버그가 있었다.

 

새로운아이디를 입력하면

페이지 가 이동되고 아이디를 출력하게 했다.

데이터베이스에도 가입한 회원의 정보가 잘 들어간것을 확인할 수있다.

반응형