회원관리 - 회원수정 Frontend

이태현·2025년 8월 16일

Web 개발

목록 보기
23/53
post-thumbnail

회원수정 버튼

  • 회원 수정 버튼이 여러 개 존재하기 때문에 id를 부여하면 안 되고 class를 부여하여 querySelectorAll()를 사용하여 처리를 해줍니다. 전에 삭제 버튼과 동일한 방식을 사용합니다.
<button class="btn btn-primary btn-sm btn_mem_edit" data-idx="<?= $row["idx"]; ?>">수정</button>
  • 해당 버튼을 forEach()를 사용하여 요소 개수만큼 기능을 부여합니다.
  // 수정 버튼
  const btn_mem_edits = document.querySelectorAll(".btn_mem_edit")

  btn_mem_edits.forEach((box) => {
    box.addEventListener("click", () => {
      const idx = box.dataset.idx

      location.href = "member_edit.php?idx=" + idx
    })
  })

회원수정 - DB

  • DB에서 idx 값을 가져와서 해당 요소에 맞게 뿌려줍니다.
// idx 회원 불러오기
  public function getInfoFormIdx($idx)
  {
    $sql = "SELECT * FROM member WHERE idx=:idx";
    $stmt = $this->conn->prepare($sql);
    $stmt->bindParam(":idx", $idx);
    $stmt->setFetchMode(PDO::FETCH_ASSOC);
    $stmt->execute();

    return $stmt->fetch();
  }

회원수정 - Main UI

  • 기존에 회원가입에 사용되었던 양식을 재사용하였습니다.
  <?php

  $g_title = "해커들의 놀이터";
  $js_array = ['js/member_edit.js'];

  $menu_code = "member";

  include "inc_common.php";
  include "inc_header.php";
  include "../inc/dbconfig.php";
  include "../inc/member.php"; // 회원관리 Class
  include "../inc/lib.php"; // 페이지네이션

  $idx = (isset($_GET["idx"]) && $_GET["idx"] != "" && is_numeric($_GET["idx"])) ? $_GET["idx"] : "";

  if ($idx == "") {
    die('
    <script>
    alert("idx값이 비어있습니다.")
    history.go(-1)
    </script>
    ');
  }

  $mem = new Member($db);

  $row = $mem->getInfoFormIdx($idx);

  ?>
  <script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>
  <main class="w-75 mx-auto border rounded-5 p-5">
    <h1 class="text-center">회원정보수정</h1>

    <form method="post" action="pg/member_process.php" name="input_form" enctype="multipart/form-data" autocomplete="off">
      <input type="hidden" name="mode" value="edit">
      <input type="hidden" name="idx" value="<?= $row["idx"]; ?>">
      <input type="hidden" name="email_chk" value="0">
      <input type="hidden" name="old_email" value="<?= $row["email"]; ?>">

      <div class="d-flex gap-2 align-items-end">
        <div>
          <label for="f_id" class="form-label">아이디</label>
          <input type="text" class="form-control" id="f_id" placeholder="아이디를 입력해 주세요." name="id" value="<?= $row["id"]; ?>">
        </div>
      </div>

      <div class="d-flex gap-2 align-items-end mt-3">
        <div class="w-25">
          <label for="f_name" class="form-label">이름</label>
          <input type="text" class="form-control" id="f_name" placeholder="이름을 입력해 주세요." name="name" value="<?= $row["name"]; ?>">
        </div>
        <div class="w-25">
          <label for="f_name" class="form-label">레벨</label>
          <select name="" id="" class="form-select">
            <option value="1" <?php if ($row["level"] == 1) echo "selected"; ?>>가입대기</option>
            <option value="2" <?php if ($row["level"] == 2) echo "selected"; ?>>준회원</option>
            <option value="3" <?php if ($row["level"] == 3) echo "selected"; ?>>정회원</option>
            <option value="10" <?php if ($row["level"] == 10) echo "selected"; ?>>관리자</option>
          </select>
        </div>
      </div>

      <div class="d-flex gap-2 mt-3 justify-content-between">
        <div class="flex-grow-1">
          <label for="f_pw" class="form-label">비밀번호</label>
          <input type="password" class="form-control" id="f_pw" placeholder="비밀번호를 입력해 주세요." name="password">
        </div>
        <div class="flex-grow-1">
          <label for="f_pw2" class="form-label">비밀번호 확인</label>
          <input type="password" class="form-control" id="f_pw2" placeholder="비밀번호 확인" name="password2">
        </div>
      </div>

      <div class="d-flex gap-2 align-items-end mt-3">
        <div class="flex-grow-1">
          <label for="f_email" class="form-label">Email</label>
          <input type="email" class="form-control" id="f_email" placeholder="이메일을 입력해 주세요." name="email" value="<?= $row["email"]; ?>">
        </div>
        <button type="button" class="btn btn-secondary" id="btn_email_chk">이메일 중복 확인</button>
      </div>

      <div class="d-flex mt-3 gap-2 align-items-end">
        <div>
          <label for="zip_code" class="form-label">우편번호</label>
          <input type="address" id="zip_code" class="form-control" readonly name="zipcode" value="<?= $row["zip_code"]; ?>">
        </div>
        <div>
          <button type="button" class="btn btn-secondary" id="btn_zipcode">우편번호찾기</button>
        </div>
      </div>

      <div class="d-flex gap-2 mt-3 justify-content-between">
        <div class="flex-grow-1">
          <label for="f_addr1" class="form-label">주소</label>
          <input type="address" class="form-control" id="f_addr1" name="addr1" value="<?= $row["addr1"]; ?>">
        </div>
        <div class="flex-grow-1">
          <label for="f_addr2" class="form-label">상세주소</label>
          <input type="address" class="form-control" id="f_addr2" placeholder="상세 주소를 입력해 주세요." name="addr2" value="<?= $row["addr2"]; ?>">
        </div>
      </div>

      <div class="d-flex mt-3 gap-5">
        <div>
          <label for="f_photo" class="form-label">프로필 이미지</label>
          <input type="file" name="photo" class="form-control" id="f_photo">
        </div>
        <?php if ($row["photo"] != "") {
          echo  '<img src="../data/profile/' . $row["photo"] . '" alt="profile" class="w-25" id="f_preview">';
        } else {
          echo  '<img src="../images/profile.png" alt="profile" class="w-25" id="f_preview">';
        } ?>
      </div>

      <div class="mt-3 d-flex gap-2 justify-content-center">
        <button type="button" class="btn btn-primary" id="btn_submit">수정확인</button>
        <button type="button" class="btn btn-secondary">수정취소</button>
      </div>
    </form>
  </main>

  <?php
  include "inc_footer.php";
  ?>

회원수정 - JS

  • 기존에 회원가입에 사용되었던 스크립트 양식을 재사용하였습니다.
document.addEventListener("DOMContentLoaded", () => {

  // 이메일 중복 확인
  const btn_email_chk = document.querySelector("#btn_email_chk")

  btn_email_chk.addEventListener("click", () => {
    const f = input_form

    if (f.old_email.value == f.email.value) {
      alert("기존 이메일과 동일합니다.")
      return false
    }
    if (f.email.value == "") {
      alert("이메일을 입력해 주세요.")
      f.email.focus()
      return false
    }
    
    // Email Ajax
    const f1 = new FormData()
    f1.append("email", f.email.value)
    f1.append("mode", "email_chk")

    const xhr = new XMLHttpRequest()
    xhr.open("POST", "../pg/member_process.php", "true")
    xhr.send(f1)

    xhr.onload = () => {
      if (xhr.status == 200) {
        const data = JSON.parse(xhr.responseText)

        if (data.result == "Email_fail") {
          alert("중복된 이메일 입니다.")
          f_email.value = ""
          f_email.focus()
        } else if (data.result == "Email_success") {
          alert("사용 가능한 이메일 입니다.")
          document.input_form.email_chk.value = 1
        } else if (data.result == "Email_format_error") {
          alert("형식이 틀린 이메일 입니다.")
          f_email.value = ""
          f_email.focus()
        }
      }
    }
  })

  // 프로필 이미지 변경시 미리 보기
  const f_photo = document.querySelector("#f_photo")
  f_photo.addEventListener("change", (e) => {
    // console.log(e)
    const reader = new FileReader()
    reader.readAsDataURL(e.target.files[0])

    reader.onload = (e) => {
      // console.log(e)
      const f_preview = document.querySelector("#f_preview")
      f_preview.setAttribute("src", e.target.result)
    }
  })

  // 우편번호 찾기
  const btn_zipcode = document.querySelector("#btn_zipcode")

  btn_zipcode.addEventListener("click", () => {
    new daum.Postcode({
      oncomplete: function (data) {
        console.log(data)
        let addr = ""
        let extra_addr = ""

        if (data.userSelectedType == "R") {
          addr = data.roadAddress
        } else {
          addr = data.jibunAddress
        }

        if (data.bname != "") {
          extra_addr = data.bname
        }

        if (data.buildingName != "") {
          if (extra_addr == "") {
            extra_addr = data.buildingName
          } else {
            extra_addr += ', ' + data.buildingName
          }
        }

        if (extra_addr != "") {
          extra_addr = ' (' + extra_addr + ')'
        }

        const zip_code = document.querySelector("#zip_code")
        zip_code.value = data.zonecode

        const f_addr1 = document.querySelector("#f_addr1")
        f_addr1.value = addr + extra_addr

        const f_addr2 = document.querySelector("#f_addr2")
        f_addr2.focus()
        console.log(data)
      }
    }).open();
  })

  // 회원수정완료 버튼
  const btn_submit = document.querySelector("#btn_submit")

  btn_submit.addEventListener("click", () => {
    const f = document.input_form
    if (f.id.value == "") {
      alert("아이디를 입력해 주세요.")
      f_id.focus()
      return false
    }

    // 이름 확인
    if (f.name.value == "") {
      alert("이름을 입력해 주세요.")
      f_name.focus()
      return false
    }

    // 비밀번호 일치 확인
    if (f.password.value != f.password2.value) {
      alert("비밀번호가 일치하지 않습니다.")
      f.password.value = ""
      f.password2.value = ""
      f.password.focus()
      return false
    }

    // 이메일 빈 칸 확인
    if (f.email.value == "") {
      alert("이메일을 입력해 주세요.")
      f.email.focus()
      return false
    }

    // 이메일 중복체크 여부 확인
    if (f.email.value != f.old_email.value) {
      if (f.email_chk.value == 0) {
        alert("이메일 중복 체크를 해주세요.")
        return false
      }
    }

    // 우편번호 확인
    if (f.zipcode.value == "") {
      alert("우편번호를 입력해 주세요.")
      return false
    }

    // 주소 확인
    if (f.addr1.value == "") {
      alert("주소를 입력해 주세요.")
      return false
    }

    // 주소2 확인
    if (f.addr2.value == "") {
      alert("상세주소를 입력해 주세요.")
      return false
    }

    f.submit()
  })
})

마무리

다음 시간에는 회원 수정 Backend 부분을 해보겠습니다.

감사합니다.

profile
이해하고 분석하고 지배한다

0개의 댓글