ID/PW 필드 입력값 유효성 검증 로직 (순한맛)

Wonkook Lee·2021년 8월 23일
26

Frontend Exercises

목록 보기
5/7
post-thumbnail

ID/PW 필드 입력값 유효성 검증 로직 (순한맛)


👌🏻 로그인을 시도하기 위한 최소한의 요구 조건

유효성을 검증하는 것은 매우 중요하다. 서버에 데이터를 요청하기 전, 사용자의 입력 값이 최소한의 요구 조건에 부합하는지 검증 하는 것은 사용자의 실수는 물론 서버로의 무작위한 요청을 방지할 수 있는 좋은 방법이다.

순한맛이라고 표현한 이유는 이번 유효성 검증의 허들은 굉장히 낮기 때문이다.

아이디에는 이메일을 나타내는 @(at)이 들어가야 하고, 비밀번호는 최소 8자리 이상이어야 로그인 버튼 풀어준다. 😤




🖨 인스타그램 로그인 페이지 따라하기

인스타그램 로고 대신 위스타그램을 넣고 나머지 포맷은 최대한 비슷하게 만들어봤다. 클로닝은 깨알같은 디테일 따라하는 맛
아이디와 비밀번호의 최소 요구 조건을 넘겨야 비활성화된 로그인 버튼이 활성화된다. 버튼이 활성화 되는 화면은 아래와 같다.

입력값이 검증되자마자 로그인 버튼이 활성화된다. 그러나 다시 비밀번호의 길이가 짧아지거나, 아이디 필드의 @이 사라지면 비활성화된다.
이 말은 즉슨 input 이벤트가 입력될 때마다 유효성 검증 함수가 호출되어야 한다는 말이 된다.




🛠 유효성 검증 로직 만들기

유효 조건을 만족하여 로그인 버튼이 활성화 되더라도 입력이 변경되어 조건을 만족시키지 못하면 다시 버튼은 비활성화 되어야 한다.
그렇다면 매번 입력이 감지될 때마다 유효성이 검증되어야 한다. 로그인 버튼이 활성화되는 조건(ID 플래그 TRUE / PW 플래그 TRUE)만 예외 처리로 두고, 나머지는 조건이 맞지 않으면 버튼 비활성화가 계속해서 이루어진다.

한 글자씩 입력될때마다 로직을 통과해야 하는 점이 비효율적이라고 생각해서 의문이었다.

실제 인스타그램 로그인 페이지를 보면 입력값이 변경될 때마다 커서가 깜빡거려서 화면 뒤의 무언가가 실행 중일 것을 짐작케 한다.
내 예상으로는 실제 유효성 검증도 매번 입력이 발생될 때마다 숨겨진 프로세스가 진행되는 것 같았다.

그렇다면 내 방법이 전혀 틀린 방법은 아니라는 가정 하에 로직을 구성해본다.




👂🏻 Input 태그에 글자를 입력하는 이벤트 감지

로그인 페이지에 input태그는 총 2개가 있다. 각각의 요소에 이벤트를 달아두는 것보다 두 input의 공통 부모에 이벤트 핸들러를 선언하고, 조건문으로 타겟의 타입이 text(id)인지 password인지 확인하여 작업을 수행하는 것이 효율적일 것 같다.

form.addEventListener('input', e => {
	if (e.target.type === 'text') { ...작업 수행...}
	if (e.target.type === 'password') { ...작업 수행...}
});

🚩 검증 절차를 위한 플래그 (true or false)

검증 절차의 요구 조건을 충족했다면 어떻게 값으로 나타낼 수 있을까?
나는 isValid라는 변수에 {id: false, pw: false} 객체를 할당했다.

만약 ID 요구 조건이 충족되었다면 isValid.id의 값은 true로 바뀌고, password의 요구 조건이 충족되었다면 isValid.pw의 값은 true가 된다.

처음엔 배열로 isValid = [false, false]; 플래그를 표현했지만, 다른 사람이 보기에 무엇에 대한 boolean값인지 명확히 할 필요가 있었다. key의 필요성을 인지했으니 객체를 사용하는 것이 바람직해보였다.

const isValid = {id: false, pw: false};
// 초기 플래그 값 false 선언

  form.addEventListener('input', e => {
    if (e.target.type === 'text') {
      isValid.id = e.target.value.indexOf('@') !== -1 ? true : false;
    }
    if (e.target.type === 'password') {
      isValid.pw = e.target.value.length >= 8 ? true : false;
    }
    validUI(isValid);
  });

	// 각 이벤트가 요구 조건을 감지하면 isValid 각 자리에 true 할당
	// 이벤트가 발생될 때마다 Validation 수행

  const validUI = function(validObj) {
    if (validObj.id && validObj.pw) { // 만약 두 값 모두 true로 들어온다면 버튼 활성화 UI
      btnLogin.removeAttribute('disabled');
    } else {
      btnLogin.setAttribute('disabled', true);
    }
  };

아래와 같이 플래그 객체가 잘 들어오는 것을 볼 수 있다.


✨ 적용 및 완성

아래와 같이 function 키워드와 코드 블럭을 괄호()로 묶고 뒤에 ()를 넣어 즉시 실행시켜주는 함수 표현 방법을 IIFE(즉시실행함수)라고 한다.

로그인과 관련된 로직(변수, 함수 등)이 외부에서 접근이 가능하면 안되기에, IIFE를 사용해서 실행할 수도, 접근할 수도 없게 했다. IIFE는 한 번 실행되고 종료되면 컨텍스트가 사라져 더 이상 접근할 수 가 없다.

하지만 이벤트 핸들러는 콜백을 클로저로 기억하고 있기 때문에 계속해서 IIFE 내부(Private) 변수와 함수를 참조하고 호출하는 것이 가능하다!

const loginValidation = (function() {

  const btnLogin = document.querySelector('.btn__login');
  const form = document.querySelector('.auth');

  const isValid = {id:false, pw:false};
  
  const validUI = function(validObj) {
    if (validObj.id && validObj.pw) {
      btnLogin.removeAttribute('disabled');
    } else {
      btnLogin.setAttribute('disabled', true);
    }
  };

  form.addEventListener('input', e => {
    if (e.target.type === 'text') {
      isValid.id = e.target.value.indexOf('@') !== -1 ? true : false;
    }
    if (e.target.type === 'password') {
      isValid.pw = e.target.value.length >= 8 ? true : false;
    }
    validUI(isValid);
  });

})();

개선 - 삼항 연산자 제거

표현문 자체로 boolean을 반환하도록 만들어서 가독성을 높인다.

  form.addEventListener('input', e => {
    if (e.target.type === 'text') {
      // isValid.id = e.target.value.indexOf('@') !== -1 ? true : false;
      isValid.id = e.target.value.includes('@');
    }
    if (e.target.type === 'password') {
      // isValid.pw = e.target.value.length >= 8 ? true : false;
      isValid.pw = e.target.value.length >= 8;
    }
    validUI(isValid);
  });


ⓒ Wonkook Lee

🙏🏻 잘못된 정보가 있다면 지적해주세요

profile
© 가치 지향 프론트엔드 개발자

2개의 댓글

comment-user-thumbnail
2021년 8월 26일

원국님 팬이에요

1개의 답글