미션4 리팩토링 기록

wonway·2024년 4월 10일
0
post-thumbnail

배경 및 목적

  1. 배경
    • 과제로 작업한 코드는 기능은 구현했으나 다른 더 좋은 방법으로 구현할 수 있었다.
    • 가독성이 떨어져서 수정하기 힘들고 코드가 너무 길다.
  2. 목적
    • 리팩토링 작업으로 더 좋은 코드를 위해 그동안 생각치 못한 부분을 생각해본다.
    • 이후에는 초기 코드의 수준이 지금보다 높아져야 한다.

방법

  1. 코드 리뷰에서 지적 받은 부분을 반영해보며 몰랐던 부분은 학습하고 적용하며 체득한다.

과정 기록

오타 수정

  1. 확장 프로그램 중에 오타를 에러 메세지로 표기해주는 것이 있다.
  2. Code Spell Checker

이벤트 유형

  1. 에러 메세지를 출력하는 기능을 focusout으로 만들었더니 제거 기능도 추가해야했다.

    > +//포커스 인 이벤트
    +emailInput.addEventListener("focusin", function (e) {
    +  e.target.style.border = "none";
    +  const message = document.querySelector(".email-error-message");
    +  if (message) {
    +    message.remove();
    +  }
    +});
    
  2. 이벤트 유형 중 ‘input’ 유형을 사용하여 값이 변화할 때 유효성 검사를 실시하여 에러 메세지를 실시간으로 출력하도록 변경했다.

    form.addEventListener("input", e => {
        setErrorMessage(e);
        checkFormValidity();
      });

에러 메세지 생성 로직

  1. 기존 생성 방식

    > +export const emailErrorMessage = (e, text) => {
    +  //빈 값일 경우 빨간 테두리 추가
    +  e.target.style.border = "1.5px solid red";
    +  //하단에 메세지 추가
    +  const message = document.createElement("span");
    +  message.textContent = `${text}`;
    +  message.style.color = "#F74747";
    +  message.style.fontSize = "15px";
    +  message.style.fontFamily = "Pretendard";
    +  message.style.fontWeight = "600";
    +  message.style.marginTop = "-16px";
    +  message.style.marginBottom = "24px";
    +  message.style.marginLeft = "16px";
    +  message.classList.add("email-error-message");
    +  message.classList.add("error");
    +  e.target.after(message);
    
  2. 이런 생성 로직을 인풋마다 달아놨다.

  3. 이벤트를 감지하면 어떤 메세지를 표시할 것인지 text인자로 전달하는 구조로 되어있었다.

  4. 리팩토링 결과

    import {
      checkEmailValidation,
      checkPasswordValidation,
      checkPasswordCheckValidation,
      checkNicknameValidation,
    } from "../utils/formValidation.js";
    
    //에러 메세지 출력 함수
    const showErrorMessage = (errorDisplayElement, errorMessage) => {
      errorDisplayElement.textContent = errorMessage;
    };
    
    export const setErrorMessage = e => {
      const password = document.querySelector("#password")?.value;
      const passwordCheck = document.querySelector("#password-check")?.value;
      let errorMessage = "";
      const value = e.target.value;
      const currentTarget = e.target.id;
      const errorDisplayElement = e.target.nextElementSibling;
    
      switch (currentTarget) {
        case "email":
          errorMessage = checkEmailValidation(value);
          break;
    
        case "password":
          errorMessage = checkPasswordValidation(value);
          break;
    
        case "password-check":
          errorMessage = checkPasswordCheckValidation(password, passwordCheck);
          break;
    
        case "nickname":
          errorMessage = checkNicknameValidation(value);
          break;
    
        default:
          break;
      }
    
      showErrorMessage(errorDisplayElement, errorMessage);
    };
    
  5. 이벤트 위임을 사용해서 form에 이벤트 리스너를 추가

  6. 유효성 검사 함수를 통해 에러 메세지를 생성

  7. 에러 메세지는 이미 존재하는 HTML 요소의 textContent로 추가

    1. 기본값은 빈 문자열로 유효성 검사 결과 에러메세지가 반환되지 않으면 빈 값이 되어 메세지가 보이지 않게되므로 제거 로직을 추가하지 않아도 된다.
  8. 이미 존재하는 HTML 요소에 CSS 스타일링을 해뒀기 때문에 자바스크립트로 style을 추가할 필요 없다.

함수 이름 형식

  1. 동사로 시작하게 변경

전체 유효성 검사 통과 시 버튼 활성화 기능

  1. 기존 코드

    > +//회원가입 활성화 상태 변경하기
    +form.addEventListener("keyup", e => {
    +  //에러 메세지 존재 유무 확인
    +  const errorMesseges = document.querySelectorAll(".error");
    +  if (
    +    errorMesseges.length === 0 &&
    +    emailCheck(emailInput.value) &&
    +    nicknameInput.length !== 0 &&
    +    passwordInput.value.length >= 8 &&
    +    passwordCheck.value.length >= 8
    +  ) {
    +    loginBtn.disabled = false;
    +    loginBtn.style.backgroundColor = "#3692ff";
    +  } else {
    +    loginBtn.disabled = true;
    +    loginBtn.style.backgroundColor = "#9ca3af";
    +  }
    +});
    
  2. 리팩토링 결과

    
    const loginBtn = document.querySelector("#login-btn");
    const signupBtn = document.querySelector("#signup-btn");
    
    function getElementValue(selector) {
      return document.querySelector(selector)?.value.trim();
    }
    
    const isValid = (validationFunction, ...args) => {
      return validationFunction(...args) === undefined;
    };
    
    export function checkFormValidity() {
      const email = getElementValue("#email");
      const password = getElementValue("#password");
      const passwordCheck = getElementValue("#password-check");
      const nickname = getElementValue("#nickname");
    
      const isEmailValid = isValid(checkEmailValidation, email);
      const isPasswordValid = isValid(checkPasswordValidation, password);
      const isPasswordCheckValid = isValid(
        checkPasswordCheckValidation,
        password,
        passwordCheck
      );
      const isNicknameValid = isValid(checkNicknameValidation, nickname);
    
      if (loginBtn) {
        isEmailValid && isPasswordValid
          ? (loginBtn.disabled = false)
          : (loginBtn.disabled = true);
      }
    
      if (signupBtn) {
        isEmailValid && isNicknameValid && isPasswordValid && isPasswordCheckValid
          ? (signupBtn.disabled = false)
          : (signupBtn.disabled = true);
      }
    }
  3. 변수 설정

    1. 요소 : 로그인 버튼, 회원가입 버튼

    2. 값 : 각 input의 값

    3. 참 거짓을 가지는 불리언 타입 변수명은 is로 시작하는 것이 일반적인 네이밍 규칙이다.

      (이것을 잘 모르고 조건문을 직접 나열해서 가독성이 떨어졌다.)

  4. 함수 설정

    1. 가독성을 증가 시키기 위해 함수getElementValue(selector)를 만들어서 사용했다.

    2. 로그인 페이지에는 닉네임 인풋과 비밀번호 재확인 인풋이 없어서 .value에 접근하는 과정에서 에러가 발생하며 멈추는 결과가 발생하는데 체이닝 연산자를 사용하여 값이 없으면 undefined를 반환하고 넘어가도록하여 스크립트 중단을 방지한다.

    3. isValid()함수 생성

      1. 기존의 유효성 검사 함수는 에러 메세지를 반환한다.
      2. 반환 결과가 없으면 isValid가 true를 반환하는 함수를 만들어서 조건문 역할을 한다.

      (함수도 불리언 값을 반환하는 함수는 변수명과 동일한 네이밍 규칙으로 만들고 조건식은 모듈화해서 가독성을 높일 수 있다.)

  5. disabled와 style을 조작했는데 disabled의 의사클래스를 사용해서 스타일을 변경할 수 있다.

    .submit:disabled {
      background-color: var(--gray400);
    }

에러 메세지 내용이 매직 리터럴

  1. 에러 메세지를 함수에 하드코딩해서 인자로 전달했었다.

  2. 리팩토링 결과

    // messages.js
    export const ERROR_MESSAGES = {
      emailEmpty: "이메일을 입력해주세요",
      emailFormat: "잘못된 이메일 형식입니다",
      password: "비밀번호를 입력해주세요",
      passwordLength: "비밀번호는 8자 이상이어야 합니다",
      passwordWrong: "비밀번호가 일치하지 않습니다",
      nicknameEmpty: "닉네임을 입력해주세요",
    };
    // formValidation.js
    //이메일 유효성 검사
    export const checkEmailValidation = value => {
      if (isEmpty(value)) {
        return ERROR_MESSAGES.emailEmpty;
      } else if (!checkEmailValidity.test(value)) {
        return ERROR_MESSAGES.emailFormat;
      }
    };
  3. 메세지를 객체로 만들어 다른 파일에 분리하였다.

  4. 매직 넘버, 매직 리터럴이라고 불리는 이런 값은 의미가 담기지 않은 값이라 가독성을 저하시킨다. 그래서 보통 의미를 담은 변수명을 만들어서 상수로 저장하여 사용한다.

이메일 형식 유효성 검사 로직

  1. 기존 코드

    > +  const atPosition = email.indexOf("@");
    +  const dotPosition = email.lastIndexOf(".");
    +  return atPosition > 0 &&
    +    dotPosition > atPosition + 1 &&
    +    dotPosition + 2 < email.length
    +    ? true
    +    : false;
    

    조건문

    • @앞에 하나 이상의 이메일 주소 이름이 있어야 한다.
    • @다음에 .이 위치해야한다.
    • .다음으로 2개 이상의 문자열이 존재해야한다.

    이 조건을 모두 참이어야 참을 반환하는 코드를 작성했다.

    그러나 정규표현식을 사용할 수 있다.

  2. 리팩토링 결과

    const checkEmailValidity = /^[A-Za-z0-9_\.\-]+@[A-Za-z0-9\-]+\.[A-Za-z0-9\-]+/;
    
    checkEmailValidity.test(value); // ture or false

    .test() 메서드는 정규 표현식을 사용하여 문자열이 특정 패턴에 맞는지 검사한다.

    이메일 형식, 전화번호 형식 등 패턴을 검증할 때 일반적으로 사용되기 때문에 정규표현식으로 검증하는 방법이 있다는 것을 기억해야겠다.

    정규 표현식이 사용되는 경우

    • 문자열의 검색, 대체, 검증
    • 패턴을 다루는 경우 (예를 들어 이메일 형식)

배운 점 요약

  1. 가독성 향상: 코드의 가독성을 높이기 위해 노력하며, 이는 유지보수성을 향상시키고, 코드의 길이를 줄이는 데에도 도움이 됩니다.
  2. 이벤트 처리: 다양한 이벤트 유형(focusout, input 등)을 활용하여 사용자 인터랙션에 대응하는 방법을 배웠습니다.
  3. 에러 메시지 처리: 에러 메시지를 효율적으로 생성하고 표시하는 방법을 개선했습니다. 이는 코드의 재사용성과 모듈성을 증가시킵니다.
  4. 유효성 검사: 입력 값의 유효성을 검사하는 함수를 작성하여, 에러 메시지를 적절하게 표시하는 방법을 배웠습니다.
  5. 함수 네이밍: 함수 이름을 동사로 시작하게 하여, 함수의 역할과 행위를 명확히 표현하는 방법을 배웠습니다.
  6. 조건부 로직 개선: 전체 유효성 검사를 통해 폼의 버튼 활성화 상태를 관리하는 로직을 개선했습니다. 이는 코드의 가독성과 효율성을 높입니다.
  7. 매직 리터럴 대체: 에러 메시지와 같은 매직 리터럴을 상수로 분리하여 관리함으로써, 코드의 유지보수성을 향상시키는 방법을 배웠습니다.
  8. 정규 표현식 활용: 정규 표현식을 사용하여 문자열의 패턴을 검증하는 기법을 배웠습니다. 이는 코드를 간결하게 만들고, 복잡한 조건을 효과적으로 처리할 수 있게 합니다.
  9. DOM 조작 최소화: HTML 요소를 미리 만들어 두고 CSS로 스타일링 한 후, JavaScript를 통해서 필요할 때만 해당 요소를 화면에 보이게 하는 방식을 배웠습니다. 이는 성능 최적화에 도움이 됩니다.
profile
문제를 컴퓨터로 해결하는 데서 즐거움을 찾는 프론트엔드 개발자

0개의 댓글

관련 채용 정보