Skip to content

Conversation

@minyoung1101
Copy link
Collaborator

요구사항

배포 링크

basic-my-pandamarket.netlify.app


기본

로그인

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

회원가입

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

심화

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

주요 변경사항

  • 지난 미션 코드리뷰 반영(메타태그 이미지 상대경로 변경)
  • input 유효성 검사, 비밀번호 표시 토글 기능 구현

스크린샷

image1-1
image1-2
image2-1
image2-2

멘토에게

  • 기능별로 함수를 나눠서 작성해보려고 했는데 어느 정도 단위로 나눠야 할 지 잘 모르겠습니다.
  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.

@minyoung1101 minyoung1101 requested a review from kiJu2 July 19, 2025 03:54
@minyoung1101 minyoung1101 added the 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. label Jul 19, 2025
@kiJu2 kiJu2 changed the base branch from main to Basic-권민영 July 22, 2025 05:02
@kiJu2
Copy link
Collaborator

kiJu2 commented Jul 22, 2025

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

@kiJu2
Copy link
Collaborator

kiJu2 commented Jul 22, 2025

기능별로 함수를 나눠서 작성해보려고 했는데 어느 정도 단위로 나눠야 할 지 잘 모르겠습니다.

크으 ~ 좋은 시도예요 벌써부터 "재사용성"을 고려하시다니... 🥺

다음 아티클을 보면 도움이 되실 것 같아요 !:

Functions should do one thing

함수는 한 가지 작업을 수행해야 합니다.

이것은 소프트웨어 엔지니어링에서 단연코 가장 중요한 규칙입니다. 함수가 한 가지 이상을 수행할 때 구성, 테스트 및 추론하기가 더 어렵습니다. 함수를 하나의 작업으로 분리할 수 있으면 쉽게 리팩토링할 수 있고 코드가 훨씬 더 깔끔하게 읽힙니다. 이 가이드에서 이것 외에 다른 것을 빼지 않는다면 당신은 많은 개발자들보다 앞서게 될 것입니다.

Bad:

function emailClients(clients: Client[]) {
  clients.forEach((client) => {
    const clientRecord = database.lookup(client);
    if (clientRecord.isActive()) {
      email(client);
    }
  });
}

Good:

function emailClients(clients: Client[]) {
  clients.filter(isActiveClient).forEach(email);
}

function isActiveClient(client: Client) {
  const clientRecord = database.lookup(client);
  return clientRecord.isActive();
}

SOLID

Copy link
Collaborator

Choose a reason for hiding this comment

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

오호 ! 유효성 검사 코드를 따로 분리하셨군요 ?

"재사용이 가능한가?"를 염두하고 설계하신거로 보여요. 훌륭합니다 👍

또한, 파일명을 유효성 검사 "함수들"을 모아놓은 js 코드임을 암시할 수 있도록 validations.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 파일에 그때그때 작성하게 되면 아래와 같은 문제가 생길 수 있어요:

  • 로직 수정 시, 모든 파일을 수정해야 해요.
  • 서로 약간씩 다른 방식으로 유사한 로직을 구현하게 되면 버그 발생 가능성이 증가합니다.
  • 공통 로직의 변화가 전체 페이지에 ripple effect(연쇄 영향)를 줄 수 있어요.

이처럼 중복된 코드가 많아질수록, 전체 프로젝트의 유지보수 비용은 계속 높아지게 됩니다.

언제 분리 해야할까 ?

사실 이건 “경험”으로 익혀가는 부분이지만, 아래와 같은 신호가 있다면 분리를 고려해볼 수 있어요:

  • "어? 이 함수 다른 데서도 쓸 것 같은데?"
  • "이거 수정하려면 다른 JS 파일에도 가서 고쳐야 하네?"
  • "이 기능이 특정 페이지에만 종속되지 않아!"
    어떻게 하면 더 나은 설계를 할 수 있을까?”를 고민하는 건 아주 중요한 개발자의 태도예요.
    정답은 없지만, 재사용성과 유지보수성이라는 기준을 계속 떠올리면서 코드를 분리하는 연습을 하다 보면,
    더욱 확장성 있는 구조를 만들 수 있게 됩니다.

Comment on lines +1 to +10
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 "";
}
Copy link
Collaborator

@kiJu2 kiJu2 Jul 22, 2025

Choose a reason for hiding this comment

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

크으~ 파라메터로 엘리먼트도 받고 있군요 !

외부 환경에 영향을 끼치지 않으면서 받은 파라메터로만 처리를 하고 있어요. 훌륭합니다.

해당 함수는 입력값이 같으면 언제나 같은 결과를 반환하고 외부 상태에 영향을 주거나 의존하지도 않아요.
이런 함수를 “순수 함수(Pure Function)” 라고 부릅니다.

이러한 구조는 테스트하기도 쉽고, 예측 가능한 코드 작성에 도움이 되는 좋은 패턴입니다.
지금처럼 유틸리티 함수를 순수하게 분리해 작성하는 습관, 정말 잘 하고 계세요! 🔥
추가로 민영님께서 만드신 이러한 함수를 "순수 함수"라고 칭합니다 😉

const parentEl = inputEl.parentElement;
const targetLabel = parentEl.firstElementChild.textContent;

let p = parentEl.querySelector("p");
Copy link
Collaborator

Choose a reason for hiding this comment

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

p 태그는 모두 가져오고 있군요 ?

현재 설계된 대로라면 동작상 문제는 없을 거로 보이지만, 만약 형제 중에 p 태그가 추가되면(이를 테면 만약 새로운 기능 중 안내 문구 같은게 추가가 된다던지) 버그가 발생할 수도 있겠어요.

에러 메시지에 고유한 식별자를 넣어도 될 것 같아요. idclass와 같이요 😉

}
p.textContent = errMsg;
} else {
p && p.remove();
Copy link
Collaborator

Choose a reason for hiding this comment

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

크으 ~ 조건문을 단축해서 사용하시다니 😇

편의상 많이 사용되는 패턴이죠 👍

Comment on lines +29 to +38
if (errMsg) {
if (!p) {
p = document.createElement("p");
p.classList.add("invalid-input");
inputEl.after(p);
}
p.textContent = errMsg;
} else {
p && p.remove();
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Guard Clause 패턴을 사용해볼 수도 있겠어요 😉:

Suggested change
if (errMsg) {
if (!p) {
p = document.createElement("p");
p.classList.add("invalid-input");
inputEl.after(p);
}
p.textContent = errMsg;
} else {
p && p.remove();
}
if (!errMsg) {
p && p.remove();
return;
}
if (!p) {
p = document.createElement("p");
p.classList.add("invalid-input");
inputEl.after(p);
}
p.textContent = errMsg;

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

@kiJu2
Copy link
Collaborator

kiJu2 commented Jul 22, 2025

수고하셨습니다 민영님 !
어떻게하면 더욱 구조적으로 더 나은 설계를 할 수 있을지에 대한 고민을 엿볼 수 있었어요 😊😊😊
제 수강생이 이러한 건설적인 고민을 한다는게 뿌듯하고 기쁘네요 😉

미션 수행하시느라 정말 수고 많으셨어요 !

@kiJu2 kiJu2 merged commit 5cdf038 into codeit-bootcamp-frontend:Basic-권민영 Jul 22, 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.

2 participants