-
Notifications
You must be signed in to change notification settings - Fork 26
[권민영] Sprint4 #88
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
The head ref may contain hidden characters: "Basic-\uAD8C\uBBFC\uC601-sprint4"
[권민영] Sprint4 #88
Changes from all commits
4991e03
8179bc3
f1c103a
e3d32a8
a9aec9b
3ccb48d
2c8b8eb
11a92bf
ceefecf
999fc9c
30b7be1
29fa0ed
e3c036e
d5bc56b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| function togglePassword(e) { | ||
| const input = e.target.parentElement.querySelector("input"); | ||
| const isOpened = input.type === "text"; | ||
| input.type = isOpened ? "password" : "text"; | ||
| e.target.classList.toggle("visible", !isOpened); | ||
| } | ||
|
|
||
| const btns = document.querySelectorAll(".btn-show").forEach((btn) => { | ||
| btn.addEventListener("click", (e) => togglePassword(e)); | ||
| }); |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,56 @@ | ||||||||||||||||||||||||||||||||||||||||||||||
| function validateInput(el, label) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const { validity } = el; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!validity.valid) { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (validity.valueMissing) return `${label}을 입력해주세요`; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (validity.typeMismatch) return "잘못된 이메일 형식입니다"; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (validity.tooShort) return "비밀번호를 8자 이상 입력해주세요"; | ||||||||||||||||||||||||||||||||||||||||||||||
| if (validity.customError) return el.validationMessage; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| return ""; | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1
to
+10
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 크으~ 파라메터로 엘리먼트도 받고 있군요 !외부 환경에 영향을 끼치지 않으면서 받은 파라메터로만 처리를 하고 있어요. 훌륭합니다. 해당 함수는 입력값이 같으면 언제나 같은 결과를 반환하고 외부 상태에 영향을 주거나 의존하지도 않아요. 이러한 구조는 테스트하기도 쉽고, 예측 가능한 코드 작성에 도움이 되는 좋은 패턴입니다. |
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| function setPasswordValidity() { | ||||||||||||||||||||||||||||||||||||||||||||||
| const [pw, pwCheck] = document.querySelectorAll("input[id^=signup_password]"); | ||||||||||||||||||||||||||||||||||||||||||||||
| if (pw.value !== pwCheck.value) { | ||||||||||||||||||||||||||||||||||||||||||||||
| pwCheck.setCustomValidity("비밀번호가 일치하지 않습니다"); | ||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||
| pwCheck.setCustomValidity(""); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| function showValidMessage(el) { | ||||||||||||||||||||||||||||||||||||||||||||||
| const inputEl = el; | ||||||||||||||||||||||||||||||||||||||||||||||
| const parentEl = inputEl.parentElement; | ||||||||||||||||||||||||||||||||||||||||||||||
| const targetLabel = parentEl.firstElementChild.textContent; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| let p = parentEl.querySelector("p"); | ||||||||||||||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||||||||||||||||||||||||||||||||||||||||||||
| let errMsg = validateInput(inputEl, targetLabel); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| if (errMsg) { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!p) { | ||||||||||||||||||||||||||||||||||||||||||||||
| p = document.createElement("p"); | ||||||||||||||||||||||||||||||||||||||||||||||
| p.classList.add("invalid-input"); | ||||||||||||||||||||||||||||||||||||||||||||||
| inputEl.after(p); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
| p.textContent = errMsg; | ||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||
| p && p.remove(); | ||||||||||||||||||||||||||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 크으 ~ 조건문을 단축해서 사용하시다니 😇편의상 많이 사용되는 패턴이죠 👍 |
||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+29
to
+38
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard Clause 패턴을 사용해볼 수도 있겠어요 😉:
Suggested change
Guard Clause을 사용하게 되면 조건부를 조기에 처리할 수 있게 되어 핵심 로직을 구분할 수 있다는 장점이 있습니다. 따라서 가독성을 향상시킬 수 있어요. 또한, 미리 조건에 따라서 데이터의 범위를 좁힐 수 있기에 핵심 로직에서는 보장받은 데이터를 편리하게 사용할 수 있다는 장점도 있어요 😊 Guard Clause ?다음과 같이 조기에 함수를 끝내는 기법을 의미합니다: function calculateDiscount(price, discountRate) {
// Guard Clause: 가격이나 할인율이 유효하지 않으면 함수 종료
if (price <= 0 || discountRate <= 0 || discountRate > 1) {
console.error("Invalid price or discount rate");
return;
}
// 할인된 가격 계산
const discountedPrice = price * (1 - discountRate);
return discountedPrice;
} |
||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| function checkBtnState(form, inputs) { | ||||||||||||||||||||||||||||||||||||||||||||||
| form.id === "signup_form" && setPasswordValidity(); | ||||||||||||||||||||||||||||||||||||||||||||||
| const btn = form.querySelector("button.large"); | ||||||||||||||||||||||||||||||||||||||||||||||
| const isValid = [...inputs].every((input) => input.validity.valid); | ||||||||||||||||||||||||||||||||||||||||||||||
| btn.classList.toggle("inactive", !isValid); | ||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const form = document.querySelector("form"); | ||||||||||||||||||||||||||||||||||||||||||||||
| const inputs = form.querySelectorAll("input"); | ||||||||||||||||||||||||||||||||||||||||||||||
| inputs.forEach((inputEl) => { | ||||||||||||||||||||||||||||||||||||||||||||||
| inputEl.addEventListener("input", () => { | ||||||||||||||||||||||||||||||||||||||||||||||
| checkBtnState(form, inputs); | ||||||||||||||||||||||||||||||||||||||||||||||
| inputEl.id === "signup_password_check" && showValidMessage(inputEl); | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
| inputEl.addEventListener("focusout", (e) => showValidMessage(e.target)); | ||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||
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코드임을 암시할 수 있도록validations.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 파일에 그때그때 작성하게 되면 아래와 같은 문제가 생길 수 있어요:
이처럼 중복된 코드가 많아질수록, 전체 프로젝트의 유지보수 비용은 계속 높아지게 됩니다.
언제 분리 해야할까 ?
사실 이건 “경험”으로 익혀가는 부분이지만, 아래와 같은 신호가 있다면 분리를 고려해볼 수 있어요:
어떻게 하면 더 나은 설계를 할 수 있을까?”를 고민하는 건 아주 중요한 개발자의 태도예요.
정답은 없지만, 재사용성과 유지보수성이라는 기준을 계속 떠올리면서 코드를 분리하는 연습을 하다 보면,
더욱 확장성 있는 구조를 만들 수 있게 됩니다.