Skip to content

Conversation

@hyunhwa21
Copy link
Collaborator

@hyunhwa21 hyunhwa21 commented Jul 22, 2025

요구사항

배포: https://preeminent-gelato-965cb7.netlify.app/login

기본

로그인

  • [x]이메일 input에서 focus out 할 때, 값이 없을 경우 input에 빨강색 테두리와 아래에 "이메일을 입력해주세요." 빨강색 에러 메세지를 보입니다.
  • [x]이메일 input에서 focus out 할 때, 이메일 형식에 맞지 않는 경우 input에 빨강색 테두리와 아래에 "잘못된 이메일 형식입니다" 빨강색 에러 메세지를 보입니다.
  • [x]비밀번호 input에서 focus out 할 때, 값이 없을 경우 아래에 "비밀번호를 입력해주세요." 에러 메세지를 보입니다
    -[x]비밀번호 input에서 focus out 할 때, 값이 8자 미만일 경우 아래에 "비밀번호를 8자 이상 입력해주세요." 에러 메세지를 보입니다.
  • [x]input 에 빈 값이 있거나 에러 메세지가 있으면 '로그인' 버튼은 비활성화 됩니다.
  • input 에 유효한 값을 입력하면 '로그인' 버튼이 활성화 됩니다.
  • []활성화된 '로그인' 버튼을 누르면 "/items" 로 이동합니다

회원가입

  • [x]이메일 input에서 focus out 할 때, 값이 없을 경우 input에 빨강색 테두리와 아래에 "이메일을 입력해주세요." 빨강색 에러 메세지를 보입니다.
  • [x]이메일 input에서 focus out 할 때, 이메일 형식에 맞지 않는 경우 input에 빨강색 테두리와 아래에 "잘못된 이메일 형식입니다" 빨강색 에러 메세지를 보입니다.
  • [x]닉네임 input에서 focus out 할 때, 값이 없을 경우 input에 빨강색 테두리와 아래에 "닉네임을 입력해주세요." 빨강색 에러 메세지를 보입니다.
  • [x]비밀번호 input에서 focus out 할 때, 값이 없을 경우 아래에 "비밀번호를 입력해주세요." 에러 메세지를 보입니다
  • [x]비밀번호 input에서 focus out 할 때, 값이 8자 미만일 경우 아래에 "비밀번호를 8자 이상 입력해주세요." 에러 메세지를 보입니다.
  • [x]비밀번호 input과 비밀번호 확인 input의 값이 다른 경우, 비밀번호 확인 input 아래에 "비밀번호가 일치하지 않습니다.." 에러 메세지를 보입니다.
  • [x]input 에 빈 값이 있거나 에러 메세지가 있으면 '회원가입' 버튼은 비활성화 됩니다.
  • [x]input 에 유효한 값을 입력하면 '회원가입' 버튼이 활성화 됩니다.
  • [x]활성화된 '회원가입' 버튼을 누르면 로그인 페이지로 이동합니다

심화

  • [x]눈 모양 아이콘 클릭시 비밀번호의 문자열이 보이기도 하고, 가려지기도 합니다.
  • [x]비밀번호의 문자열이 가려질 때는 눈 모양 아이콘에는 사선이 그어져있고, 비밀번호의 문자열이 보일 때는 사선이 없는 눈 모양 아이콘이 보이도록 합니다.

주요 변경사항

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

스크린샷

image

멘토에게

  • 구현에만 너무 치중 된 느낌이 들기는 합니다.
    for문도 많이 쓴 거 같고, return 을 너무 많이 사용해서 적절하지 않은 것 같기도 한데 다른 방식을 사용하기가 아직 어렵네요.
    많은 도움이 필요합니다...^^;;;;
  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.

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
@hyunhwa21 hyunhwa21 added the 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. label Jul 22, 2025
@kiJu2
Copy link
Collaborator

kiJu2 commented Jul 24, 2025

스프리트 미션 하시느라 수고 많으셨어요.
현화님 학습에 도움 되실 수 있게 꼼꼼히 리뷰 하도록 해보겠습니다. 😊

@kiJu2
Copy link
Collaborator

kiJu2 commented Jul 24, 2025

구현에만 너무 치중 된 느낌이 들기는 합니다.
for문도 많이 쓴 거 같고, return 을 너무 많이 사용해서 적절하지 않은 것 같기도 한데 다른 방식을 사용하기가 아직 어렵네요.
많은 도움이 필요합니다...^^;;;;


아이구 ㅎㅎㅎ 한 번 보고 현화님께 도움될 수 있도록 피드백 해볼게요 !! 😉

@import url(fonts.css);

body {
width: calc(100vw - calc(100vw - 100%));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혹시 해당 스타일은 어떤 의미가 있는걸까요?

Copy link
Collaborator

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 등등이 있을 것 같아요 !

Copy link
Collaborator

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)과 같이 '�함수의 목적이 명확한 단위' 그리고 '재사용성이 필요한' 함수들을 공통 모듈로서 관리를 하고, 각 페이지에서는 엘리먼트와 관련된 핸들러 함수들을 처리하는게 어떨까요?

물론, 어떤 기준으로 파일을 분리하고 함수를 분리하는 지에 대해서는 앞으로 많은 코드들을 다루고, 다른 사람이 작성한 코드들을 들여다보면서 많은 인사이트를 얻을 수 있으실거예요.

Comment on lines +64 to +72
USER_INPUT[i].addEventListener("keyup", (e) => {
targetInput = e.target;
inputParent = targetInput.closest(".input-group");

clearTimeout(timer);
timer = setTimeout(() => {
targetInput.value !== "" ? callBackCheck() : false;
}, delay);
});
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

사용자는 피드백을 빠르게 받는 것을 선호합니다 !

현재 요구사항은 딜레이를 넣지 않아도 문제를 해결할 수 있을거예요.
0.5초의 텀을 유저가 기다려야 하는 것은 사용성이 좋지 못할 수 있겠네요 😉

Comment on lines +2 to +6
const USER_INPUT = Array.from(document.getElementsByTagName("input")).filter(
(input) => {
return input.getAttribute("name") !== "showCheck";
}
); // 비밀번호 입력 보기 체크 박스 제외
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

만약. "비밀번호 입력 보기 체크 박스"와 유사한 input이 추가 된다면?

현재 코드에서는 nameshowCheckinput만을 제외하고 있습니다.
이 방식은 지금 당장은 잘 동작하지만, 앞으로 "showCheck"처럼 제외해야 할 input이 한두 개 더 늘어나게 되면, 매번 조건을 추가해줘야 하므로 코드가 점점 복잡해지고 유지보수가 어려워질 수 있어요. 🤔

공통적인 식별자를 넣어볼 수 있을 것 같아요:

Suggested change
const USER_INPUT = Array.from(document.getElementsByTagName("input")).filter(
(input) => {
return input.getAttribute("name") !== "showCheck";
}
); // 비밀번호 입력 보기 체크 박스 제외
const USER_INPUT = Array.from(document.querySelectorAll(".form-data"));

Comment on lines +2 to +6
const USER_INPUT = Array.from(document.getElementsByTagName("input")).filter(
(input) => {
return input.getAttribute("name") !== "showCheck";
}
); // 비밀번호 입력 보기 체크 박스 제외
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

또한, 해당 변수는 '상수'로 보기는 어려워요.

대문자 + 스네이크 케이스의 경우 관례적으로 "상수"를 의미합니다 !
하지만 지금 상황은 상수가 아닌 변수로 볼 수 있어요.

Suggested change
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";

Comment on lines +44 to +74
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);
});
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기가 말씀주신 for이 많아졌다는 곳이군요 !

Suggested change
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을 대체해볼 수 있을거예요 ! 😉

Comment on lines +89 to +111
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);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(생각해보기) 해당 함수가 콜백일 필요가 있을까요?

Suggested change
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;
}

//전체 유효성 확인
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굿굿 ! 주석을 꼼꼼히 잘 작성하셨네요 😉

@kiJu2
Copy link
Collaborator

kiJu2 commented Jul 24, 2025

수고하셨습니다 현화님~!!
미션 수행하시느라 정말 고생 많으셨어요!
전반적으로 로직에 대한 고민의 흔적이 잘 보였고, 유효성 검증 처리도 꼼꼼하게 해주셨네요 😊

이제는 코드의 재사용성과 사용자 경험도 함께 챙겨보면 실력이 더 빨리 늘 거예요!

앞으로도 현화님의 성장을 기대해봅니다 ! 💪

@kiJu2 kiJu2 merged commit 52763ef into codeit-bootcamp-frontend:Basic-김현화 Jul 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants