web/javascript 기초

[javascript] 회원가입 폼 오류 수정하기

xudegloss 2023. 3. 6. 01:05

1. 회원가입 폼 오류 확인하기

처음에는 발견하지 못했는데, 강의를 수강하다가 알게 되었다. 

- 인증번호 받기를 여러 번 클릭하면 여러 번 시간 반복 함수가 실행되어 서로 화면 갱신하기 위하여 충돌이 발생한다. 

- setInterval 함수가 종료되지 않아서 계속 else 구문을 반복한다.

2가지 문제점이 발생하였고, 문제점을 해결해보자.

2. 회원가입 폼 오류 수정하기

2-1. 인증번호 받기 버튼 제어하기

인증번호 받기 버튼을 제어하기 위하여 버튼의 상태를 Boolean을 통하여 설정한다.

상태를 제어하는데에 Boolean이 많이 사용되므로, 자주 이용하기. 주의할 점은 시간은 함수 내에 지정해야 하고, 버튼 상태는 함수 밖에 지정해야 한다. 그래야 시간은 계속하여 갱신되어 나중에 버튼을 눌러도 실행되지만, 상태는 안에 저장해버리면 계속 갱신되어서 설정한 의미가 없어지기 때문이다.

2-2. setInterval 함수 종료하기

else 구문에서 빠져나오지 않는 것을 확인할 수 있다. 이것은 시간 반복 함수가 종료되지 않아서 벌어지는 일이다. setInterval 함수를 멈추기 위하여 clearInterval 함수를 이용하면 된다.

  1. 변수를 생성한다.
  2. 생성된 변수에 setInterval 함수를 할당한다.
  3. else 구문 안에서 clearInterval(변수) 실행한다.

이 순서대로 실행한다면 시간 반복 함수를 종료하고, else에서 빠져나올 수 있을 것이다.

 

3. 코드

3-1. html 코드

<!DOCTYPE html>
<html lang="ko">
  <head>
    <title>회원가입</title>
    <script src="./06-timer.js" defer></script>
    <link rel="stylesheet" href="./06-timer.css" />
  </head>
  <body>
    <div class="container">
      <h3 class="header">회원가입</h3>
      <div class="wrapper">
        <input class="input" type="email" placeholder="codecamp@gamil.com" />
        <div class="wrapper__middle">
          <input class="input" type="tel" placeholder="010-1234-5678" />
          <button class="get__number" onclick="takeTarget()">
            인증번호 받기
          </button>
        </div>
        <div class="wrapper__bottom">
          <input
            class="input__target"
            type="text"
            maxlength="6"
            placeholder="123456"
            id="target__number"
          />
          <span class="target__time">
            <span id="remaining__min">3</span> :
            <span id="remaining__sec">00</span>
          </span>
          <button class="complete__target" id="complete">인증완료</button>
        </div>
      </div>
      <button class="join__btn">가입하기</button>
    </div>
  </body>
</html>

3-2. css 코드

* {
  box-sizing: border-box;
  margin: 0px;
}

html,
body {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.container {
  width: 450px;
  height: 280px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  padding: 20px;
}

.wrapper {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  padding: 20px;
}

.wrapper__middle {
  width: 100%;
  display: flex;
  flex-direction: row;
  align-items: center;
}

.get__number {
  width: 50%;
  height: 40px;
  border: 1px solid #83dcb7;
  color: #83dcb7;
  border-radius: 5px;
  margin-left: 8px;
  background-color: white;
}

.wrapper__bottom {
  width: 100%;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
  align-items: center;
}

.target__time {
  display: flex;
  flex-direction: row;
  margin-left: 10px;
  font-weight: 700;
}

.input {
  width: 100%;
  height: 40px;
  padding: 5px;
  border: 1px solid #c4c4c4;
  border-radius: 5px;
}

.input__target {
  width: 65%;
  height: 40px;
  padding: 5px;
  border: 1px solid #c4c4c4;
  border-radius: 5px;
}

.complete__target {
  height: 40px;
  background-color: #83dcb7;
  border: 1px solid #c4c4c4;
  border-radius: 5px;
  font-weight: 700;
  color: white;
  padding: 10px;
}

.join__btn {
  width: 90%;
  height: 40px;
  background-color: #83dcb7;
  border: 1px solid #c4c4c4;
  border-radius: 5px;
  font-weight: 700;
  color: white;
  padding: 10px;
}

3-3. javascript 코드

const remainingMin = document.getElementById("remaining__min");
const remainingSec = document.getElementById("remaining__sec");
const completeBtn = document.getElementById("complete");
const input = document.getElementById("target__number");

// 굳이 ms로 변경할 필요가 없다. 계산하기 더 불편하고 할 이유가 없다.
// 항상 상황에 따라서 달라진다.

// 문제점 발생 (1) : 인증번호 받기를 여러 번 누르게 되면 계속 새로운 시간 업데이트 되어서 시간에 영향을 준다.
// 문제점 발생 (2) : else를 나가지 못 하고, 계속 작동하게 된다. > setInterval 함수 빠져나가기.
let isStarted = false;

const takeTarget = () => {
  // 변경하지 않으면 조건문을 물어보는 의미가 없다. 왜냐하면 항상 true 이기 때문이다.
  // 계속 눌러도 false 이기 때문에 다른 시간에 영향 받지 않는다.
  // 일단 인증번호 입력값 안에 담아주기. > 그리고 카운트 시작하기.
  if (isStarted === false) {
    // 타이머가 작동하지 않는 경우
    isStarted = true;
    completeBtn.style.backgroundColor = "#83dcb7";
    // 시간을 함수 안에 넣어줘야 계속 갱신이 된다.
    let time = 180; // 3분
    let timer;

    input.value = String(Math.floor(Math.random() * 100000)).padStart(6, "0");
    timer = setInterval(function () {
      if (time >= 0) {
        // time = time - 1; // 여기서 빼줘야 3분에서 3분 또 출력되지 않고, 바로 2분 59초로 넘어간다.
        let min = Math.floor(time / 60);
        let sec = String(time % 60).padStart(2, "0");
        remainingMin.innerText = min;
        remainingSec.innerText = sec;
        time = time - 1;
      } else {
        completeBtn.style.backgroundColor = "tomato";
        isStarted = false;
        clearInterval(timer);
      }
    }, 1000);
  } else {
    // 타이머가 작동하는 경우
  }
  // alt + 방향키 위 : 안 쪽으로 이동시킬 수 있다.
};

4. 완성된 회원가입 폼

잘 작동하는 것을 확인할 수 있다.