본문 바로가기
코드 개념 메모장

회원 관리 시스템 구현: 회원 가입 시 클라이언트 단 유효성 검사 (JavaScript 활용)

by 코딩 중인 호빵밍 2024. 12. 10.

 요약 

입력 값 유효성 검사

  • 아이디, 비밀번호, 닉네임에 대해 JavaScript를 활용한 클라이언트 측 유효성 검사 구현
  • 아이디, 닉네임 입력 여부를 확인하고, 미입력 시 alert로 사용자에게 알림
  • 각 입력값에 대해 길이 제한 및 정규식 검사 수행
  • 비밀번호는 입력된 두 값이 일치하는지 실시간으로 검사하며, 별도의 버튼 없이 즉시 표시
  • 모든 유효성 검사 결과는 지정된 메시지 영역에 실시간 출력, 성공 시 초록색, 실패 시 빨간색 스타일 적용

JavaScript 활용

  • JavaScript의 addEventListener() 메서드를 사용하여 input 이벤트를 바인딩함으로써,
    사용자가 값을 입력할 때마다 유효성 검사가 실시간으로 실행되도록 구현
  • 검사 결과는 지정된 메시지 영역에 즉시 출력되며,
    유효한 경우에는 초록색(text-success), 유효하지 않은 경우에는 빨간색(text-danger)으로 스타일이 적용됨
  • 메시지 출력 로직은 공통 함수로 분리하여 코드의 일관성, 가독성, 재사용성을 높임

기술 개념 정리

  • 불리언 변수 네이밍
    조건을 나타내는 변수는 보통 조건을 묻는 형태로 네이밍 하는 것이 관례이기 때문에 isSuccess라 정의했다.
  • classList
    자바스크립트에서 HTML 요소의 클래스를 추가하거나 제거할 수 있 속성이다. 예시) add("클래스명") 클래스 추가
  • DOM(Document Object Model)
    HTML을 자바스크립트가 다룰수 있도록 트리구조로 표현한 객체이며, DOM요소는 HTML 안의 각각의 태그(<div>, <input>, <p> 등) 를 자바스크립트로 가져왔을 때의 자체이다.
  • 이벤트 리스너 (addEventListener)
    사용자의 입력이나 클릭 같은 동작을 감지해, 특정 함수를 실행하도록 연결하는 자바스크립트 내장 메서드이다.

완성된 회원가입 화면입니다.
사용자가 정확하고 유효한 정보를 입력할 수 있도록, 실시간 입력값 검증과 피드백 기능을 구현했습니다.

JavaScript를 활용해 회원가입 폼에서,

아이디, 비밀번호, 닉네임 등의 입력 값을 프론트엔드(클라이언트 측)에서 어떻게 유효성 검사했는지 정리하고자 합니다.

 

 입력값 유효성 검사     

 아이디 (loginId) 

<div class="mb-3">
  <div class="input-group">
    <input type="text" id="loginId" name="loginId" class="form-control" required maxlength="20" placeholder="아이디를 입력하세요">
    <button type="button" class="btn btn-outline-dark" onclick="checkLoginId()">중복 확인</button>
  </div>
  <div id="loginIdCheckResult" class="mt-2"></div> <!-- 아이디 중복 확인 내용 출력 -->
</div>
  • required와 maxlength="20"을 통해 필수 입력 및 최대 길이를 제한했습니다.
  • "중복 확인" 버튼 클릭 시 checkLoginId() 함수가 실행되어 서버에 중복 여부를 확인합니다. (서버 단 유효성 검사에서 작성)
  • 결과 메시지는 id="loginIdCheckResult" 에 출력되며, JavaScript로 성공/실패 여부에 따라 동적으로 스타일을 적용합니다.
// loginId를 확인하기 위한 함수
function checkLoginId() {
    const loginId = document.getElementById('loginId').value;
    const resultLoginId = document.getElementById('loginIdCheckResult');

	// loginId 입력 여부
    if(!loginId) {
        setResultMessage(resultLoginId,"");
        alert("아이디를 입력하세요.");
        return;
    }

    // 정규식 검사 (맨 앞자리는 영어 소문자, 그 뒤는 소문자와 숫자만 허용)
    const regex = /^[a-z][a-z0-9]*$/;
        if (!regex.test(loginId)) {
        setResultMessage(resultLoginId, "아이디는 영어 소문자로 시작하고, 숫자만 포함할 수 있습니다.", false);
        return;
    }

    // loginId 길이 유효성 검사
    if (loginId.length < 5 || loginId.length > 20) {
        setResultMessage(resultLoginId,"아이디는 5자 이상 20자 이하여야 합니다.",false);
        return;
    }
}

 

아이디 유효성 검사 함수 (checkLoginId())

  • 사용자가 입력한 loginId 값을 가져와 빈 값 여부, 정규식 형식, 길이 조건을 순차적으로 검증합니다.
  • 정규식: ^[a-z][a-z0-9]*$
    → 영어 소문자로 시작하고, 영문 소문자 및 숫자만 허용
  • 길이 제한: 5자 이상 20자 이하
  • 응답 결과에 따라 loginIdCheckResult 영역에 사용 가능 여부를 표시하고, 스타일(class)을 동적으로 적용합니다.
// 메시지 출력 로직 통합 함수
function setResultMessage(element, message, isSuccess) {
    if (message) {
        element.textContent = message;
        element.classList.remove("text-danger", "text-success", "small-text");
        element.classList.add(isSuccess ? "text-success" : "text-danger", "small-text");
    } else {
        clearResultMessage(element);
    }
}
// 메시지 초기화 함수
function clearResultMessage(element) {
    element.textContent = "";
    element.classList.remove("text-danger", "text-success", "small-text");
}

 

메시지 출력 및 초기화 유틸(공통) 함수 (setResultMessage())

  • 아이디 유효성 검사 결과를 출력할 공통 함수를 만들었습니다.
  • 메시지 상태에 따라 성공/실패 클래스를 동적으로 설정합니다.
  • 메시지가 없는 경우에는 clearResultMessage()를 호출해 초기화합니다.

공통함수를 쓰기 전과 후 비교

  • 기존 방식
    // 공통 함수 도입 전
    resultPassword.textContent = "비밀번호가 일치하지 않습니다.";
    resultPassword.classList.remove("text-success");
    resultPassword.classList.add("text-danger");
    메시지를 출력할 때마다 textContent를 설정하고,
    Bootstrap 스타일 클래스는 HTML 상단에 CSS CDN 링크를 추가하고, 직접 classList를 통해 추가/제거하거나
    또는 <head> 영역에 .text-success { color: red; }처럼 직접 CSS를 정의하여 사용할 수 있습니다.

    하지만 기존 방식은 조건이 많아질수록 코드가 반복되어 길어지고, 가독성과 유지보수가 어려워지는 단점이 있었습니다.

  • 공통 함수 적용
    // 공통 함수 도입 후
    setResultMessage(resultPassword, "비밀번호가 일치하지 않습니다.", false);
     setResultMessage(element, message, isSuccess) 함수를 정의하여, 메시지의 출력과 스타일 적용을 통합했습니다.
    element는 메시지를 출력할 DOM 요소(resultPassword 등),
    message는 출력할 텍스트,
    isSuccess는 메시지의 성공여부를 나타내는 boolean 타입 값으로 정의했습니다.
    적용 예시) setResultMessage(resultPassword, "비밀번호가 일치하지 않습니다.", false);

메시지의 유무와 상태에 따라 출력되는 텍스트와 스타일을 하나의 공통 함수로 통합 처리함으로써,

💡 중복 제거, 가독성 향상, 유지보수 및 재사용성에서 높은 개선 효과를 얻을 수 있었습니다.

 

비밀번호 (password, passwordConfirm) 

<div class="mb-3">
  <div class="input-group">
  <input type="password" id="password" name="password" class="form-control" required maxlength="100" placeholder="비밀번호를 입력하세요">
  <input type="password" id="passwordConfirm" name="passwordConfirm" class="form-control" required maxlength="100" placeholder="비밀번호 확인">
</div>
  <div id="passwordCheckResult" class="mt-2"></div> <!-- 비밀번호 일치 여부 내용 출력 -->
</div>
  • 비밀번호 입력과 확인의 특성 상 두개의 <input> 요소를 작성했습니다.
  • required, maxlength="100" 속성을 통해 필수 입력과 길이를 제한했습니다.
  • 결과 메시지는 id="passwordCheckResult" 에 출력되며, JavaScript로 성공/실패 여부에 따라 동적으로 출력합니다.
// password를 확인하기 위한 함수
// 비밀번호 확인 이벤트 연결
document.getElementById('password').addEventListener('input', checkPassword);
document.getElementById('passwordConfirm').addEventListener('input', checkPassword);

function checkPassword() {
  const password = document.getElementById('password').value;
  const passwordConfirm = document.getElementById('passwordConfirm').value;
  const resultPassword = document.getElementById('passwordCheckResult');
  
    // 비밀번호 입력 여부
   if (!password || !passwordConfirm) {
      setResultMessage(resultPassword, "비밀번호를 모두 입력해 주세요.", false);
      return;
   }

  // 비밀번호 길이 유효성 검사
  if (password.length < 8 || password.length > 20) {
    setResultMessage(resultPassword, "비밀번호는 8자 이상 20자 이하여야 합니다.", false);
    return;
  }

  // 정규식 검사
  const regex = /^(?=.*[a-zA-Z])(?=.*[!@#$%^&*]).*$/
  if(!regex.test(password)){
    setResultMessage(resultPassword, "비밀번호는 영문자와 특수문자를 반드시 포함해야 합니다.", false);
    return;
  }

  // 비밀번호 일치 여부 확인
  if(password === passwordConfirm) {
    setResultMessage(resultPassword, "비밀번호가 일치합니다.", true);
  } else {
    setResultMessage(resultPassword, "비밀번호가 일치하지 않습니다.", false);
  }
}

 

비밀번호 확인 함수 (checkPassword())

  • 사용자가 입력한 password와 passwordConfirm 값을 가져와 길이 조건, 정규식 형식, 일치 여부를 순차적으로 검증합니다.
  • 길이 제한: 8자 이상 20자 이하
  • 비밀번호 관련 두 입력 필드에 대해 input 이벤트를 바인딩하여, 입력할 때마다 실시간으로 유효성을 검사하도록 구현합니다.
     별도의 버튼 없이 사용자가 값을 입력할 때마다 checkPassword() 함수가 실행되어 실시간 피드백 제공
  • 정규식: ^(?=.*[a-zA-Z])(?=.*[!@#$%^&*]).*$
    → 영문자 1개 이상, 특수문자 1개 이상 포함 필수
  • 유효성 검사 결과는 passwordCheckResult 영역에 출력됩니다.
      setResultMessage() 공통 함수를 통해 메시지와 스타일이 함께 적용되며, 성공 여부에 따라 Bootstrap 클래스인 text-success 또는 text-danger가 동적으로 적용됩니다.

 닉네임 (nickname) 

<div class="mb-3">
  <div class="input-group">
    <input type="text" id="nickname" name="nickname" class="form-control" required maxlength="20" placeholder="닉네임을 입력하세요">
    <button type="button" class="btn btn-outline-dark" onclick="checkNickname()">중복 확인</button>
  </div>
  <div id="nicknameCheckResult" class="mt-2"></div> <!-- 닉네임 중복 확인 결과 출력 -->
</div>
  • required와 maxlength="20"을 통해 필수 입력 및 최대 길이를 제한했습니다.
  • "중복 확인" 버튼 클릭 시 checkNickname() 함수가 실행되어 서버에 중복 여부를 확인합니다. (서버 단 유효성 검사에서 작성)
  • 결과 메시지는 id="nicknameCheckResult" 에 출력되며, 성공/실패 여부에 따라 동적으로 스타일을 적용합니다.
// nickname을 확인하기 위한 함수
function checkNickname() {
  const nickname = document.getElementById('nickname').value;
  const resultNickname = document.getElementById('nicknameCheckResult');

  // 닉네임 입력 여부
  if(!nickname) {
    setResultMessage(resultNickname, "", false);
    alert("별명을 입력하세요.");
    return;
  }

  // 닉네임 길이 유효성 검사
  if(nickname.length < 2 || nickname.length > 15) {
    setResultMessage(resultNickname, "별명은 2자 이상 15자 이하여야 합니다.", false);
    return;
  }

}

 

닉네임 중복 확인 함수 (checkNickname())

  • 사용자가 입력한 nickname 값을 가져와 빈 값 여부, 길이 조건을 순차적으로 검증합니다.
  • 길이 제한: 2자 이상 20자 이하
  • 응답 결과에 따라 nicknameCheckResult 영역에 사용 가능 여부를 표시하고, 스타일(class)을 동적으로 적용합니다.

 개발 회고 

회원가입 폼을 설계하고 JavaScript로 유효성 검사를 구현하는 과정에서,

처음에는 각 입력 필드에 대한 기본적인 HTML과 JavaScript를 활용하여 유효성 검사를 구현하는데 집중했습니다.

 

특히 비밀번호 확인 부분은 별도의 버튼 없이, 두 입력 값을 실시간으로 비교하도록 구현하면서 JavaScript의 addEventListener()와  정규식 검사 등 다양한 방식의 유효성 검사를 적용해볼 수 있었습니다.

또한, 유효성 검사 메시지 출력을 공통 함수로 분리하며 중복 제거, 가독성 향상, 유지보수성 개선이라는 코드 구조의 중요성을 실감할 수 있었습니다.

 

이번 구현을 통해 클라이언트 단에서 입력값을 실시간으로 검사하고 처리하는 흐름을 이해하게 되었고,  다음 글에서는 서버와의 비동기 통신을 통해 아이디·닉네임의 중복 여부를 확인하고 프론트엔드와 백엔드가 실제로 어떻게 연결되어 동작하는지 더 깊이 확인해볼 수 있을 것입니다.

 

느리더라도 코드를 직접 작성하고 흐름을 이해해가며 구현하는 방식이, 지금의 제게 가장 적합한 학습법이라는 것도 이번 경험을 통해 다시 한 번 느꼈습니다.