순수 자바스크립트 기반 회원 가입 폼 검증 로직 구현 가이드

마크업 구조 설정

회원 정보 수집을 위한 폼 요소는 데이터 속성 (data attributes) 을 활용하여 자바스크립트에서 접근성을 높이는 것이 좋다. 각 입력 필드에는 필수 값을 강제하거나 패턴 매칭을 위한 속성을 명시적으로 정의한다.

<div class="auth-wrapper">
  <form id="newAccountForm">
    
    <div class="field-group">
      <label>아이디</label>
      <input type="text" id="reg_id" name="userid" minlength="4" required data-validate="alpha_num">
      <span class="msg-display" id="err_reg_id"></span>
    </div>

    <div class="field-group">
      <label>비밀번호</label>
      <input type="password" id="reg_pwd" name="password" minlength="8" required data-validate="complex_pwd">
      <span class="msg-display" id="err_reg_pwd"></span>
    </div>

    <div class="field-group">
      <label>비밀번호 재확인</label>
      <input type="password" id="reg_confirm" name="re_password" required>
      <span class="msg-display" id="err_re_pwd"></span>
    </div>

    <div class="field-group">
      <label>이메일 주소</label>
      <input type="email" id="reg_email" name="email_address" required>
      <span class="msg-display" id="err_mail"></span>
    </div>

    <button type="submit">계정 생성 완료</button>
  </form>
</div>

입력 시 실시간 유효성 검토

사용자가 필드를 조작할 때마다 현재 값의 유효성을 즉시 확인해야 한다. 이를 위해 `input` 이벤트를 바인딩하고, 정규식을 적용하여 조건 위반 여부를 판단한다. 실패 시 오류 메시지를 표시하고 성공 시 클리어한다.

const formInputs = {
  reg_id: document.getElementById('reg_id'),
  reg_pwd: document.getElementById('reg_pwd'),
  reg_confirm: document.getElementById('reg_confirm'),
  reg_email: document.getElementById('reg_email')
};

function validateId(e) {
  const targetId = 'reg_id';
  const errorMsg = document.getElementById(`err_${targetId}`);
  const value = e.target.value.trim();
  
  // 대소문자 영문과 숫자, 밑줄 허용
  const idPattern = /^[A-Za-z0-9_]+$/;
  
  if (!idPattern.test(value)) {
    errorMsg.textContent = '특수 문자는 사용할 수 없습니다.';
  } else {
    errorMsg.textContent = '';
  }
}

function validatePassword(e) {
  const targetId = 'reg_pwd';
  const errorMsg = document.getElementById(`err_${targetId}`);
  const value = e.target.value;
  
  const hasUpper = /[A-Z]/.test(value);
  const hasLower = /[a-z]/.test(value);
  const hasNum = /[0-9]/.test(value);
  
  if (!hasUpper || !hasLower || !hasNum) {
    errorMsg.textContent = '비밀번호는 대소문자와 숫자를 모두 포함해야 합니다.';
  } else {
    errorMsg.textContent = '';
  }
}

// 이벤트 리스너 등록
Object.values(formInputs).forEach(input => {
  input.addEventListener('input', (e) => {
    if (input.id === 'reg_id') validateId(e);
    if (input.id === 'reg_pwd') validatePassword(e);
  });
});

폼 제출 전 최종 점검

사용자가 전송 버튼을 클릭하면 기본 동작을 막아야 한다. 모든 필드가 올바르게 작성되었는지 종합적으로 점검하며, 비밀번호 일치 여부 등 상호 의존적 규칙을 여기서 처리한다.

document.getElementById('newAccountForm').addEventListener('submit', function(e) {
  e.preventDefault();
  let submitAllowed = true;

  const idVal = document.getElementById('reg_id').value;
  const pwdVal = document.getElementById('reg_pwd').value;
  const cfmPwdVal = document.getElementById('reg_confirm').value;
  const mailVal = document.getElementById('reg_email').value;

  // 아이디 길이 체크
  if (idVal.length < 4) {
    document.getElementById('err_reg_id').textContent = '아이디는 최소 4 자 이상이어야 합니다.';
    submitAllowed = false;
  }

  // 비밀번호 길이 체크
  if (pwdVal.length < 8) {
    document.getElementById('err_reg_pwd').textContent = '비밀번호 길이가 부족합니다.';
    submitAllowed = false;
  }

  // 비밀번호 불일치 체크
  if (pwdVal !== cfmPwdVal) {
    document.getElementById('err_re_pwd').textContent = '비밀번호가 일치하지 않습니다.';
    submitAllowed = false;
  }

  // 이메일 포맷 체크
  const mailRegex = /[\w-\.]+@([\w-]+\.)+[\w-]{2,4}/;
  if (!mailRegex.test(mailVal)) {
    document.getElementById('err_mail').textContent = '올바른 이메일 형식이 아닙니다.';
    submitAllowed = false;
  }

  if (submitAllowed) {
    console.log('전송 준비됨: 서버로 데이터 이동');
    // this.submit();
  }
});

시각적 피드백 스타일링

사용자는 시각적인 힌트를 통해 상태 변화를 알아야 한다. 유효성이 검증된 필드는 녹색 테두리로, 오류가 발생한 필드는 붉은색 테두리와 텍스트로 강조한다.

.msg-display {
  color: #e74c3c;
  font-size: 12px;
  display: block;
  margin-top: 4px;
  min-height: 1.2em;
}

/* 유효성 검사가 통과된 경우 */
.newAccountForm input:valid {
  border-color: #2ecc71;
}

/* 오류 발생 시 */
.newAccountForm input:invalid:not(:placeholder-shown) {
  border-color: #e74c3c;
}

서버 연동 아키텍처 점검

중복 계층 검증을 위해서는 백엔드 API 와 통신이 필요하다. 사용자가 입력을 종료했을 때 (`blur`) 호출하여 중복 여부를 서버에서 확인할 수 있다.

document.getElementById('reg_id').addEventListener('blur', async function() {
  const userId = this.value;
  const errorSpan = document.getElementById('err_reg_id');

  if (userId.length >= 4) {
    try {
      const url = `/api/v1/users/exist?id=${encodeURIComponent(userId)}`;
      const res = await fetch(url);
      const json = await res.json();
      
      if (json.isUsed) {
        errorSpan.textContent = '사용 중인 아이디입니다.';
      }
    } catch (err) {
      console.error('ID 체크 중 오류 발생');
    }
  } else {
    errorSpan.textContent = '';
  }
});

태그: JavaScript form-validation dom-events frontend-ui API-Integration

8월 6일 19:20에 게시됨