Vanilla JS Toy 프로젝트 - 1. Form Validator (javascript편)

falconlee236

·

2022. 1. 9. 23:37

반응형

여기에 올라온 모든 프로젝트와 소스코드는 here 여기서 확인할 수 있다.

vanilla javascript Toy project 1. Form Validator


대망의 자바스크립트 부분까지 왔다. 간단한 웹사이트를 만드는데 필요한 설명이 이렇게 길어질줄 몰랐다. 진짜 일주일에 한번이 아니라 한달에 한번씩 업로드를 해야하는 상황도 올 수 있을 것 같다. 상대적으로 자바스크립트는 이번 웹 사이트에서 설명할 것이 좀 적기 때문에 이번 글로 다 마무리 할 것 같다. 이번 글에서 소개할 내용은 다음과 같다.

  1. 이번 프로젝트에서 사용할 DOM 구성요소 간단 설명
  2. 프로젝트에서 사용되는 모든 함수 설명
  3. ShowError, ShowSuccess 로직 설명
  4. 이벤트 등록하기

0. INTRO


vanilla javascript에서 html, css요소 객체를 얻기 위해서는 DOM트리가 어떻게 이루어져 있는지를 알아야 한다. 이 과정은 생각보다 복잡하기 때문에 이 복잡함을 줄이려고 JQuery가 등장해서 지금까지 사용되고 있었지만 요즘은 JQuery가 저물어 가는 추세이고, 순수 자바스크립트에서는 외부 프레임워크를 사용하지 않고 js에서 제공하는 기본 툴만을 사용해서 자바스크립트 자체에 대한 이해를 높이자는 것이 목적이니 결국은 DOM을 알아야 반응형 웹 사이트를 만들 수 있다. 여기서는 DOM에 대한 설명은 이미 구글링을 해서 대략적으로 알고 있다는 전제하에 설명한다. 만약 모르는 사람은 바로 구글가서 검색해보자.

 

반응형

1. DOM Element 가져오기


  1. 일단 DOM 요소를 가져오는 방법은 여러가지가 있다.
    • id값으로 가져오는 getElementById
    • tag이름으로 가져오는 getElementByTagName
    • class이름으로 가져오는 getElementByclassname
    • query 선택자로 가져오는 querySelector, querySelectorall
      나는 이 수많은 DOM요소를 가져오는 방법중에서 getElementById와 querySelector를 추천한다. 왜냐하면 이 둘은 모두 단일 요소 그 자체를 가져오는 반면, 다른 방법은 HTMLCollection이나 NodeList 형식으로 요소를 가져오기 때문이다. 나는 하나의 요소를 가져오고 싶었는데, 변수에 배열 값이 저장되면 결국 오류가 날 가능성이 높다. 따라서 단일 요소를 가져오는 두 방법을 사용하는 것이 디버깅하는데 용이하다.
  2. 우리 프로젝트에서 사용할 주된 DOM객체는 다음과 같다.
    • 제출 양식을 담당하는 form태그 요소를 저장하는 form 변수
    • username 입력하는 input요소를 저장하는 username 변수
    • email 입력하는 input요소를 저장하는 email 변수
    • password 입력하는 input요소를 저장하는 password 변수
    • 다시 passoword를 입력하는 input요소를 저장하는 password2 변수
    • const form = document.getElementById('form'); const username = document.getElementById("username"); const email = document.getElementById("email"); const password = document.getElementById("password"); const password2 = document.getElementById("password2");
반응형

2. 이벤트 등록하기


  1. 버튼을 누르면 색깔이 바뀌게 하고 싶고, 오류 메시지를 출력하고 싶은가? 이처럼 특정 행동을 하면 설정한 행동을 실행하게 해주는 것을 이벤트라고 하고 이 이벤트가 저장되어 있는 객체를 이벤트 핸들러(event handler) 혹은 이벤트 리스너(event listener)라고 한다.
  2. 이번 프로젝트에서 이벤트는 단 하나이다. 버튼을 눌렀을때, 어떤 행동을 하자. 버튼을 누르는 경우는 여러가지이다. submit버튼을 누르거나, input에 입력을 한 다음에 enter키를 누를때와 같은 경우가 있다. 그렇다면 이 모든 경우를 고려해서 모두 이벤트를 만들어서 등록해야 할까? 자바스크립트에는 이런 상황에 대처하기 위해서 이벤트 전파라는 기능을 제공한다. 자세한것은 재쳐두고
<html>
    <form>
        <input>
    </form>
</html>

이런식으로 태그가 구성되어 있는데, input에 이벤트가 발생하면 html태그 부터 이벤트가 발생한 지점인 input까지 이벤트가 전파 되고, input에서 발생된 이벤트가 form, html로 순차적으로 전파가 된다. 그렇기 때문에 form안에 수많은 input태그가 있어도 결국에는 form태그에서 한번에 관리할 수 있게 되고, 부모 태그가 자식태그의 이벤트를 관리하는 것을 이벤트 위임 (event delegation)이라고 한다.

  1. 그런데 한가지 문제가 있다. 기본적으로 이벤트가 발생하면 미리 설정된 default값이 발생하는데, submit태그는 새 창을 열어서 이동한다. 우리는 이 기능을 구현하지 않을 것이다. 따라서 default 이벤트를 막아야 하는데 이것을 하게 해주는 함수가 바로 preventDefault()이다.
  2. 이 이벤트는 어떻게 등록할까? 다른 방법은 여러 단점이 많아서 나는 addEventListener를 사용하는 것을 추천한다.
    • EventTarget의 addEventListener() 메서드는 지정한 이벤트가 대상에 전달될 때마다 호출할 함수를 설정합니다. 일반적인 대상은 Element, Document, Window지만, XMLHttpRequest와 같이 이벤트를 지원하는 모든 객체를 대상으로 지정할 수 있습니다. 출처
  3. 우리는 eventListener를 form 요소에 등록할 것인데, 모든 input에 값이 들어있다면 그냥 통과하게 하고, 하나라도 값이 존재하지 않으면 전수조사가 들어가게 만들것이다. 간단한 프로젝트이기 때문에 자잘한 에러같은 경우는 넘기자. 이 기능을 하는 함수인 checkRequired, check함수에 대해서는 다음 챕터에서 설명할 것이다.
form.addEventListener('submit', e => {
    e.preventDefault();
    if(checkRequired([username, email, password, password2])){
        checkLength(username, 3, 15);
        checkLength(password, 6, 25);
        checkEmail(email);
        checkPasswordsMatch(password, password2);
    }
});
반응형

3. 함수 설명


  1. checkRequired(inputArr)
    inputArr에 있는 모든 요소들이 모두 1개 이상의 문자열을 가지고 있는지 검사. 하나라도 없으면 true, 모두 있으면 _true_를 return
    • Arr에 있는 모든 원소를 forEach함수를 사용해서 원소를 input 매개변수에 담는다. 그리고 각 DOM elemnt에 input값을 받는 속성은 value를 사용하면 된다. 이 값 양옆에 공백을 제거하기 위해서 string.trim()함수를 사용하는 것은 센스.
function checkRequired(inputArr){
    let isRequired = false;
    inputArr.forEach(input => {
        if(input.value.trim() === ''){
            showError(input, `${getFieldName(input)} is required`);
            isRequired = true;
        }else{
            showSucceess(input);
        }
    });

    return isRequired;
}
  1. getFieldName(input)
    input에 있는 element의 이름을 받아오는 함수이다. 우리는 html를 코딩 할 때 id값을 이름으로 설정을 했기 때문에 단순하게 각 element의 id값을 가져오면 되고 element에 있는 id속성에 접근하면 된다.
    function getFieldName(input){
     return input.id.charAt(0).toUpperCase() + input.id.slice(1);
    }
  1. showSuccess(input), showError(input, message)
    form-control 클래스에 sucess, error를 추가해주는 함수이다. 그런데 우리는 지금 모두 input태그에 있는 요소만 저장한 변수를 가지고 있다. 그러면 이 form-control클래스는 어떻게 접근할까? 답은 태그의 계층 구조에 있다. input태그의 부모 요소가 바로 form-control 클래스를 가지고 있는 div이므로 현재 input요소의 부모 요소를 가져오면 된다. 그 방법은 parentElement 메소드를 사용하는 것이다.
    • parentElement 메소드로 불러온 부모 요소의 클래스 값을 바꿔주려면 요소에 있는 className 속성을 바꾸기만 하면 된다.
    • error인 경우에는 error메시지도 출력해야 하는데, 이 메시지 내용도 javascript에서 받아와서 small태그를 선택한 다음 innerText 속성에 message 값을 대입하면 쉽게 해결된다.
function showError(input, message){
    const formControl = input.parentElement;
    formControl.className = 'form-control error';
    const small = formControl.querySelector('small');
    small.innerText = message;
}

function showSucceess(input){
    const formControl = input.parentElement;
    formControl.className = 'form-control success';
}

나머지 함수들은 이름의 길이가 제한에 맞는지, email이 양식에 맞는지, 비밀번호가 동일하게 입력되었는지 구현하는 함수를 만들면 되고 이것은 여러분이 할 수 있을 것이라고 생각한다. 조금만 힌트를 준다면 email 양식을 체크하는 방법은 정규표현식을 사용하면 되고 구글링하면 다 나온다.

해설 코드는 다음과 같다.

function checkLength(input, min, max){
    if(input.value.length < min){
        showError(input, `${getFieldName(input)} must be at least ${min} characters`);
    }else if(input.value.length > max){
        showError(input, `${getFieldName(input)} must be less than ${max} characters`);
    }else{
        showSucceess(input);
    }
}

function checkEmail(email){
    const regEmail = /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/;
    if (regEmail.test(input.value.trim())) {
        showSuccess(input);
      } else {
        showError(input, 'Email is not valid');
      }
}

function checkPasswordsMatch(input1, input2){
    if(input1.value !== input2.value){
        showError(input2, 'Passwords do not match');
    }
}
반응형

4. 마무리


이제 총 4페이지에 걸친 첫번째 바닐라 자바스크립트 토이 프로젝트 설명이 완료되었다. 간단한 프로젝트라고 생각했는데 다른 사람에게 설명을 한다고 하니 엄청 시간이 오래걸렸다. 하지만 결국 지식을 말하고 설명하려고 하면 훨씬 더 많이 배우는 것 같다. 아는 것이라고 생각해도 막상 설명을 하려면 엄청나게 어려운게 사실이기 때문이다. 따라서 더 많은 것을 공부해야 하는 것이 설명하는 사람이자 강사라고 생각한다. 다음에는 영화 예매를 하는 간단한 웹을 만들어 보려고 한다. 제발 다음 글도 읽어주세요~~

반응형