-
Notifications
You must be signed in to change notification settings - Fork 26
[김현화] sprint4 #91
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[김현화] sprint4 #91
The head ref may contain hidden characters: "Basic-\uAE40\uD604\uD654-sprint4"
Conversation
feat: style.css - 비밀번호 보기/감추기 input 포커스 적용 feat: style.css - login,signup min-height 수정 feat: variable.css - 에러 색상 추가 feat: image 폴더 images로 이름 변경/ html, css 이미지 경로 수정 feat: login.html, signup.html 헤드 스크립트 라인 추가 feat: signup.html 중복 아이디 수정, 닉네임 길이값 추가 feat: js폴더 생성: login.js, moduless.js, signup.js
|
스프리트 미션 하시느라 수고 많으셨어요. |
|
구현에만 너무 치중 된 느낌이 들기는 합니다. 아이구 ㅎㅎㅎ 한 번 보고 현화님께 도움될 수 있도록 피드백 해볼게요 !! 😉 |
| @import url(fonts.css); | ||
|
|
||
| body { | ||
| width: calc(100vw - calc(100vw - 100%)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
혹시 해당 스타일은 어떤 의미가 있는걸까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
해당 파일이 어떤 파일인지 나타나면 좋을 것 같아요 !
파일명만 보아도 어떤 코드인지 유추할 수 있도록 직관적인 파일명을 짓는게 어떨까요? 😊
예를 들어서
common.js,auth.js,auth-element-handlers.js등등이 있을 것 같아요 !
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(생각해보기/심화) 두 페이지를 하나의 js로만 운용했을 때의 문제점.
각각의 페이지가 함께 사용하고 있던 함수나 변수는 강한 의존성을 가지게 됩니다.
만약 signup.html에서만 email에 대해 validate를 사용하고 signin.html에서는 email validate를 해제해달라는 요구사항이 추가 된다면 코드에 조건문이 추가되겠죠?
이렇게 각 페이지에 독립적인 요구사항들이 추가될 수록 코드의 복잡도는 증가하게 됩니다 !
그렇다면 어떻게 할까요?
공통적인 부분들. 그리고 유지보수에 용이한 설계가 필요해요. 예를 들어서 isValidEmail(email: string)과 같이 '�함수의 목적이 명확한 단위' 그리고 '재사용성이 필요한' 함수들을 공통 모듈로서 관리를 하고, 각 페이지에서는 엘리먼트와 관련된 핸들러 함수들을 처리하는게 어떨까요?
물론, 어떤 기준으로 파일을 분리하고 함수를 분리하는 지에 대해서는 앞으로 많은 코드들을 다루고, 다른 사람이 작성한 코드들을 들여다보면서 많은 인사이트를 얻을 수 있으실거예요.
| USER_INPUT[i].addEventListener("keyup", (e) => { | ||
| targetInput = e.target; | ||
| inputParent = targetInput.closest(".input-group"); | ||
|
|
||
| clearTimeout(timer); | ||
| timer = setTimeout(() => { | ||
| targetInput.value !== "" ? callBackCheck() : false; | ||
| }, delay); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사용자는 피드백을 빠르게 받는 것을 선호합니다 !
현재 요구사항은 딜레이를 넣지 않아도 문제를 해결할 수 있을거예요.
0.5초의 텀을 유저가 기다려야 하는 것은 사용성이 좋지 못할 수 있겠네요 😉
| const USER_INPUT = Array.from(document.getElementsByTagName("input")).filter( | ||
| (input) => { | ||
| return input.getAttribute("name") !== "showCheck"; | ||
| } | ||
| ); // 비밀번호 입력 보기 체크 박스 제외 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
만약. "비밀번호 입력 보기 체크 박스"와 유사한 input이 추가 된다면?
현재 코드에서는 name이 showCheck인 input만을 제외하고 있습니다.
이 방식은 지금 당장은 잘 동작하지만, 앞으로 "showCheck"처럼 제외해야 할 input이 한두 개 더 늘어나게 되면, 매번 조건을 추가해줘야 하므로 코드가 점점 복잡해지고 유지보수가 어려워질 수 있어요. 🤔
공통적인 식별자를 넣어볼 수 있을 것 같아요:
| const USER_INPUT = Array.from(document.getElementsByTagName("input")).filter( | |
| (input) => { | |
| return input.getAttribute("name") !== "showCheck"; | |
| } | |
| ); // 비밀번호 입력 보기 체크 박스 제외 | |
| const USER_INPUT = Array.from(document.querySelectorAll(".form-data")); |
| const USER_INPUT = Array.from(document.getElementsByTagName("input")).filter( | ||
| (input) => { | ||
| return input.getAttribute("name") !== "showCheck"; | ||
| } | ||
| ); // 비밀번호 입력 보기 체크 박스 제외 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
또한, 해당 변수는 '상수'로 보기는 어려워요.
대문자 + 스네이크 케이스의 경우 관례적으로 "상수"를 의미합니다 !
하지만 지금 상황은 상수가 아닌 변수로 볼 수 있어요.
| const USER_INPUT = Array.from(document.getElementsByTagName("input")).filter( | |
| (input) => { | |
| return input.getAttribute("name") !== "showCheck"; | |
| } | |
| ); // 비밀번호 입력 보기 체크 박스 제외 | |
| const formDataElements = Array.from(document.getElementsByTagName("input")).filter( | |
| (input) => { | |
| return input.getAttribute("name") !== "showCheck"; | |
| } | |
| ); // 비밀번호 입력 보기 체크 박스 제외 |
상수는 보통 다음과 같은 상황에서 사용됩니다. 😉:
const MAX_RETRY_COUNT = 3;
const API_ENDPOINT = "https://example.com/api";
const DEFAULT_LANGUAGE = "ko";| export function formCheck() { | ||
| for (let i = 0; i < USER_INPUT.length; i++) { | ||
| //포커스를 잃었을때 | ||
| USER_INPUT[i].addEventListener("focusout", (e) => { | ||
| targetInput = e.target; | ||
| inputParent = targetInput.closest(".input-group"); | ||
|
|
||
| let moveTarget = e.relatedTarget; | ||
| let targetTag = moveTarget.tagName == "INPUT"; //이동한 요소 확인 | ||
|
|
||
| //input으로 이동 했을 때만 에러 메세지 출력 | ||
| if (targetTag) { | ||
| callBackCheck(); | ||
| } else { | ||
| targetInput = ""; | ||
| inputParent = ""; | ||
| } | ||
| }); | ||
|
|
||
| // 입력이 끝났을 때 | ||
| USER_INPUT[i].addEventListener("keyup", (e) => { | ||
| targetInput = e.target; | ||
| inputParent = targetInput.closest(".input-group"); | ||
|
|
||
| clearTimeout(timer); | ||
| timer = setTimeout(() => { | ||
| targetInput.value !== "" ? callBackCheck() : false; | ||
| }, delay); | ||
| }); | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
여기가 말씀주신 for이 많아졌다는 곳이군요 !
| export function formCheck() { | |
| for (let i = 0; i < USER_INPUT.length; i++) { | |
| //포커스를 잃었을때 | |
| USER_INPUT[i].addEventListener("focusout", (e) => { | |
| targetInput = e.target; | |
| inputParent = targetInput.closest(".input-group"); | |
| let moveTarget = e.relatedTarget; | |
| let targetTag = moveTarget.tagName == "INPUT"; //이동한 요소 확인 | |
| //input으로 이동 했을 때만 에러 메세지 출력 | |
| if (targetTag) { | |
| callBackCheck(); | |
| } else { | |
| targetInput = ""; | |
| inputParent = ""; | |
| } | |
| }); | |
| // 입력이 끝났을 때 | |
| USER_INPUT[i].addEventListener("keyup", (e) => { | |
| targetInput = e.target; | |
| inputParent = targetInput.closest(".input-group"); | |
| clearTimeout(timer); | |
| timer = setTimeout(() => { | |
| targetInput.value !== "" ? callBackCheck() : false; | |
| }, delay); | |
| }); | |
| } | |
| } | |
| export function formCheck() { | |
| USER_INPUT.forEach((inputEl) => { | |
| inputEl.addEventListener("focusout", handleFocusOut); | |
| inputEl.addEventListener("keyup", handleKeyup); | |
| }); | |
| } | |
| function handleFocusOut(e) { | |
| targetInput = e.target; | |
| inputParent = targetInput.closest(".input-group"); | |
| const moveTarget = e.relatedTarget; | |
| const movedToInput = moveTarget?.tagName === "INPUT"; | |
| if (movedToInput) { | |
| callBackCheck(); | |
| } else { | |
| targetInput = ""; | |
| inputParent = ""; | |
| } | |
| } | |
| function handleKeyup(e) { | |
| targetInput = e.target; | |
| inputParent = targetInput.closest(".input-group"); | |
| clearTimeout(timer); | |
| timer = setTimeout(() => { | |
| if (targetInput.value !== "") { | |
| callBackCheck(); | |
| } | |
| }, delay); | |
| } |
위와 같이 함수를 분리하고 forEach를 통해 for을 대체해볼 수 있을거예요 ! 😉
| function errorCheck(input, wrap, callback) { | ||
| let error = true; | ||
| if (input.value === "") { | ||
| error = spaceCheck(wrap); | ||
| } else { | ||
| switch (input.getAttribute("name")) { | ||
| case "userEmail": | ||
| error = checkEmail(input, wrap); | ||
| break; | ||
| case "nickName": | ||
| error = nickNameCheck(input, wrap); | ||
| break; | ||
| case "password": | ||
| error = checkPassword(input, wrap); | ||
| break; | ||
| case "passwordCheck": | ||
| error = reconfirm(input, wrap); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| callback(error); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(생각해보기) 해당 함수가 콜백일 필요가 있을까요?
| function errorCheck(input, wrap, callback) { | |
| let error = true; | |
| if (input.value === "") { | |
| error = spaceCheck(wrap); | |
| } else { | |
| switch (input.getAttribute("name")) { | |
| case "userEmail": | |
| error = checkEmail(input, wrap); | |
| break; | |
| case "nickName": | |
| error = nickNameCheck(input, wrap); | |
| break; | |
| case "password": | |
| error = checkPassword(input, wrap); | |
| break; | |
| case "passwordCheck": | |
| error = reconfirm(input, wrap); | |
| break; | |
| } | |
| } | |
| callback(error); | |
| } | |
| function errorCheck(input, wrap) { | |
| let error = true; | |
| if (input.value === "") { | |
| error = spaceCheck(wrap); | |
| } else { | |
| switch (input.getAttribute("name")) { | |
| case "userEmail": | |
| error = checkEmail(input, wrap); | |
| break; | |
| case "nickName": | |
| error = nickNameCheck(input, wrap); | |
| break; | |
| case "password": | |
| error = checkPassword(input, wrap); | |
| break; | |
| case "passwordCheck": | |
| error = reconfirm(input, wrap); | |
| break; | |
| } | |
| } | |
| return error; | |
| } |
return으로 하는게 콜백 지옥에 빠지지 않을 수 있고 함수로 전달을 강제할 필요가 없어서 개발 편의성도 높아질거예요 !
콜백 지옥은 JavaScript를 이용한 비동기 프로그래밍시 발생하는 문제로서, 함수의 매개 변수로 넘겨지는 콜백 함수가 반복되어 코드의 들여쓰기 수준이 감당하기 힘들 정도로 깊어지는 현상을 말한다.
| return false; | ||
| } | ||
|
|
||
| //전체 유효성 확인 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
굿굿 ! 주석을 꼼꼼히 잘 작성하셨네요 😉
|
수고하셨습니다 현화님~!! 이제는 코드의 재사용성과 사용자 경험도 함께 챙겨보면 실력이 더 빨리 늘 거예요! 앞으로도 현화님의 성장을 기대해봅니다 ! 💪 |
요구사항
배포: https://preeminent-gelato-965cb7.netlify.app/login
기본
로그인
-[x]비밀번호 input에서 focus out 할 때, 값이 8자 미만일 경우 아래에 "비밀번호를 8자 이상 입력해주세요." 에러 메세지를 보입니다.
회원가입
심화
주요 변경사항
feat: style.css - 비밀번호 보기/감추기 input 포커스 적용
feat: style.css - login,signup min-height 수정
feat: variable.css - 에러 색상 추가
feat: image 폴더 images로 이름 변경/ html, css 이미지 경로 수정
feat: login.html, signup.html 헤드 스크립트 라인 추가
feat: signup.html 중복 아이디 수정, 닉네임 길이값 추가
feat: js폴더 생성: login.js, moduless.js, signup.js
스크린샷
멘토에게
for문도 많이 쓴 거 같고, return 을 너무 많이 사용해서 적절하지 않은 것 같기도 한데 다른 방식을 사용하기가 아직 어렵네요.
많은 도움이 필요합니다...^^;;;;