inflearn logo
강의

강의

N
챌린지

챌린지

멘토링

멘토링

N
클립

클립

로드맵

로드맵

지식공유

[코드캠프] 부트캠프에서 만든 고농축 프론트엔드 코스

▶ final 과제

이번 final 과제 피드백 부탁드립니다!

해결된 질문

213

개발하는 알파카

작성한 질문수 2

0

안녕하세요! 강의 잘 듣고 있습니다!

이번 과제 코드 피드백 부탁드립니다!

고맙습니다.

<화면>

<html>

<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <title>SignUp</title>
  <link rel="stylesheet" href="./final.css">
  <script defer src="./final.js"></script>
</head>
<body>
  <div class="wrapper">
    <div class="wrapper__header">
      <span id="header__title">코드캠프 회원가입</span>
    </div>
    <div class="wrapper__body">
      <div class="wrapper__text">
        <input type="text" id="email" placeholder="이메일을 입력해 주세요.">
        <span class="errorMsg email">이메일이 올바르지 않습니다.</span>
        <input type="text" id="name" placeholder="이름을 입력해 주세요.">
        <span class="errorMsg name">이름이 올바르지 않습니다.</span>
        <input type="text" id="pw1" placeholder="비밀번호를 입력해 주세요.">
        <span class="errorMsg pw1">비밀번호를 입력해주세요.</span>
        <input type="text" id="pw2" placeholder="비밀번호를 다시 입력해 주세요.">
        <span class="errorMsg pw2">비밀번호를 입력해주세요.</span>
      </div>
      <div class="wrapper__phone" oninput="phone()">
        <input type="text" id="num1" maxlength="3"> -
        <input type="text" id="num2" maxlength="4"> -
        <input type="text" id="num3" maxlength="4">
      </div>
      <div class="wrapper__certification">
        <div class="cert__number">
          <span id="certNum">000000</span>
          <button class="chkBtn" disabled="true">인증번호 전송</button>
        </div>
        <div class="cert__time">
          <span id="certTimer">3:00</span>
          <button class="chkBtn" disabled="true">인증완료</button>
        </div>
      </div>
      <div class="wrapper__select">
        <div class="select__locale">
          <select id="locale">
            <option selected disabled>지역을 선택하세요</option>
            <option value="서울">서울</option>
            <option value="경기">경기</option>
            <option value="인천">인천</option>
          </select>
          <span class="errorMsg locale">지역을 선택해주세요.</span>
        </div>
        <div class="select__gender">
          <label for="woman">
            <input type="radio" name="gender" id="woman"> 여성
          </label>
          <label for="man">
            <input type="radio" name="gender" id="man"> 남성
          </label>
        </div>
        <span class="errorMsg gender">성별을 선택해주세요.</span>
      </div>
    </div>
    <div class="divideLine"></div>
    <div class="wrapper__check">
      <!-- <button class="submit" disabled="true">가입하기</button> -->
      <button class="submit">가입하기</button>
    </div>
  </div>
</body>
</html>

 

<css>

*{
  box-sizing: border-box;
  margin: 0;
}
html, body{
  width: 540px;
}
.chkBtn{
  width: 120px;
  height: 40px;
  border: 1px solid #D2D2D2;
  border-radius: 7px;
  font-size: 16px;
  font-weight: 400;
  color: #0068FF;
  background-color: #FFF;
  cursor: pointer;
}
.chkBtn.active {
  width: 120px;
  height: 40px;
  border: 1px solid #D2D2D2;
  border-radius: 7px;
  font-size: 16px;
  font-weight: 400;
  background-color: #0068FF;
  color: #FFF;
  cursor: pointer;
}
.errorMsg{
  width: 100%;
  color: red;
  font-size: 10px;
  display: flex;
  flex-direction: column;
  align-items: center;
  visibility: hidden;
}
.wrapper{
  width: 100%;
  height: 100%;
  padding: 60px 80px;
  border: 1px solid #AACDFF;
  border-radius: 20px;
  box-shadow: 7px 7px 39px rgba(0, 104, 255, .25);
}

.wrapper__header{
  width: 100%;
  font-size: 32px;
  font-weight: 700;
  color: #0068FF;
  padding-bottom: 60px;
}

.wrapper__body{
  width: 100%;
}
.wrapper__text > input{
  width: 100%;
  height: 60px;
  margin-top: 20px;
  font-size: 16px;
  font-weight: 400;
  border: 1px solid #D2D2D2;
  border-radius: 7px;
  padding: 18px;
}

.wrapper__phone{
  width: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px 0;
}
.wrapper__phone > input{
  width: 100px;
  height: 40px;
  border: 1px solid #D2D2D2;
  border-radius: 7px;
}

.wrapper__certification {
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  justify-content: space-between;
}
#certNum, #certTimer{
  color: #0068FF;
  font-size: 18px;
  padding-right: 20px;
}
.cert__time{
  padding: 20px 0;
}

.wrapper__select{
  width: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.select__locale{
  width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
#locale{
  width: 100%;
  height: 60px;
  border: 1px solid #D2D2D2;
  border-radius: 7px;
  color: #797979;
  font-size: 16px;
  font-weight: 400;
  padding: 18px;
}
.select__gender{
  width: 140px;
  display: flex;
  justify-content: space-between;
  padding-top: 30px;
}

.divideLine{
  width: 100%;
  border: 1px solid #E6E6E6;
  margin: 20px 0;
}

.wrapper__check{
  width: 100%;
  display: flex;
  justify-content: center;
}
.submit {
  width: 100%;
  height: 60px;
  font-size: 18px;
  font-weight: 400;
  color: #0068FF;
  background-color: #FFF;
  border: 1px solid #0068FF;
  border-radius: 7px;
}

 

<js>

const submit = document.querySelector('.submit'); // 가입하기
const numberChk = document.querySelector('.cert__number .chkBtn'); // 인증번호 전송
const timeChk = document.querySelector('.cert__time .chkBtn'); // 인증완료

let time = 180; // 180초, 인증 시간
let isStarted = false;

// email
const emailChk = () => {
  let email = document.getElementById('email').value;
  if(email.includes('@') === true){
    let isEmail = email.split('@')[1].includes('.');
    if(isEmail === false){
      document.querySelector('.errorMsg.email').style.visibility = 'visible';
      document.querySelector('.errorMsg.email').value = '';
      return false;
    } else {
      document.querySelector('.errorMsg.email').style.visibility = 'hidden';
      return true;
    }
  } else {
    document.querySelector('.errorMsg.email').style.visibility = 'visible';
    document.getElementById('email').value = '';
    return false;
  }
}

// name
const nameChk = () => {
  let name = document.getElementById('name').value;
  if(name.length === 0){
    document.querySelector('.errorMsg.name').style.visibility = 'visible';
    return false;
  } else {
    document.querySelector('.errorMsg.name').style.visibility = 'hidden';
    return true;
  }
}

// pw
const pwChk = () => {
  let pw1 = document.getElementById('pw1').value;
  let pw2 = document.getElementById('pw2').value;
  if(pw1 && pw2){
    if(pw1 === pw2){
      document.querySelector('.errorMsg.pw1').style.visibility = 'hidden';
      document.querySelector('.errorMsg.pw2').style.visibility = 'hidden';
      return true;
    } else {
      document.querySelector('.errorMsg.pw1').style.visibility = 'visible';
      document.querySelector('.errorMsg.pw2').style.visibility = 'visible';
      document.querySelector('.errorMsg.pw1').innerHTML = '비밀번호가 일치하지 않습니다.'
      document.querySelector('.errorMsg.pw2').innerHTML = '비밀번호가 일치하지 않습니다.'
      return false;
    }
  } else {
    document.querySelector('.errorMsg.pw1').style.visibility = 'visible';
    document.querySelector('.errorMsg.pw2').style.visibility = 'visible';
    return false;
  }
}

// phone
const phone = () => {
  let num1 = document.getElementById('num1').value;
  let num2 = document.getElementById('num2').value;
  let num3 = document.getElementById('num3').value;
  if(num1.length === 3) {
    document.getElementById('num2').focus();
    if(num2.length === 4) {
      document.getElementById('num3').focus();
    }
  }
  if(num1.length === 3 && num2.length === 4 && num3.length === 4){
    numberChk.classList.add('active');
    certification();
  }
}

const certification = () => {
  // 인증번호
  numberChk.disabled = false;
  numberChk.addEventListener('click', e => {
    let randomNumber = String(Math.trunc(Math.random() * 1000000)).padStart(6, '0')
    document.getElementById('certNum').innerText = randomNumber;

    // 타이머
    if(isStarted === false){
      isStarted = true;
      timeChk.disabled = false;
      let timer = setInterval(() => {
        if(time >= 0){
          let min = Math.trunc(time / 60);
          let sec = String(time % 60).padStart(2,'0');
          document.getElementById('certTimer').innerText = `${min}:${sec}`;
          time--;
        } else {
          clearTime(timer);
        }
      }, 100)
      timeChk.addEventListener('click', e => {
        if(time >= 0){
          alert('인증이 완료 되었습니다.');
          clearTime(timer);
          submit.disabled = false;
        }
      })
    }
  })
}

const clearTime = (timer) => {
  timeChk.classList.remove('active');
  numberChk.classList.remove('active');
  document.getElementById('certNum').innerText = '000000';
  document.getElementById('certTimer').innerText = '0:00';
  timeChk.disabled = true;
  numberChk.disabled = true;
  isStarted = false;
  clearInterval(timer);
}

const checkValidation = () => {
  emailChk();
  nameChk();
  pwChk();
  if(emailChk() && nameChk() && pwChk()) {
    return true;
  } else {
    return false;
  }
}

// 검증
submit.addEventListener('click', e => {
  checkValidation();
  if(checkValidation()){
    alert('코드캠프 가입을 축하합니다.');
  }
});

react node.js seo graphql next.js

답변 1

0

노원두

안녕하세요! 지루한 들소님!

전체적으로 코드를 깔끔하게 작성하신 것이 눈에 보입니다!^^
앞으로도 계속 이렇게 만들어 주세요!

실제로 실무에서 여럿이 협업을 하다보면, 코드가 깔끔해야 레고 블록 조립하듯이 붙였다 떼었다 하는 느낌으로 유지보수 하실 수 있어요!

 

코드를 한 곳에 모두 작성하는 것이 아닌, emailChk(), pwChk() 등의 형태로 함수로 분리하여 읽기가 쉬워지는 것 같네요!^^
좋은 부분이라고 생각되며, 이런 코드가 많아서 내가 아닌 다른 사람이 굳이 이해하려고 하지 않고, 눈으로만 보더라도 읽힌다면 그게 바로 좋은 코드라고 할 수 있겠죠?!^^

* 참고) "이건 어려운 작업이라, 아무나 못 하는거야! 나만 이해할 수 있어! 모르면 나한테 물어봐!"
=> 대부분의 이런 경우는 사실 좋은 코드라고 보기는 어려울 것 같네요!^^

 

뒷 수업에서 더 좋은 코드를 만들기 위한 리팩토링(다시 더 좋은 방법으로 만들기) 방법들을 많이 배우니, 앞으로도 이렇게 꾸준히 학습해요!^^

fetchBoardsOfMine, fetchBoardsCountOfMine 에러 문의드립니다

0

36

1

댓글 기능 구현 중 질문드립니다.

0

66

1

쿠폰코드 발급

0

133

2

example 서버 플레이그라운드, API 접속 모두 안됩니다.

0

86

2

문의드립니다!! ㅠㅠ

0

101

2

graphql 백엔드 서버가 포폴용 빼곤 접속이 안됩니다.

0

76

2

_app.js 작성 이후로 에러가 발생하네요

0

93

2

학습자료

0

70

2

학습자료가 안열립니다.

0

49

2

플레이 그라운드 퀴즈 문제 질문이 있습니다.

0

59

0

기존강의 구매자, 업데이트 끝인가요?

0

109

3

업데이트 버전 수강

0

88

2

완벽한 프론트엔드

0

136

2

나만의 쇼핑몰 샘플 페이지 접속 확인부탁드립니다.

0

83

1

graphql 접속이 안됩니다.

0

100

2

const, let 사용 질문 드립니다.

0

70

2

싸이월드 만들기 1탄 피드백 부탁드립니다.

0

122

2

회원가입 과제 피드백 부탁드립니다.

0

80

2

styled.span / styled.input "CSS 자동완성"

0

47

1

쿠폰 발급 관련

0

166

2

서버 502 error

0

247

2

쿠폰 다시 부탁드려도 될가여?

0

140

2

a태그 패딩했을때 왜 크기가 줄어들지 않고 늘어나나요

0

184

2

2분 44초 질문

0

131

3