Skip to content

[김동희] Sprint4 #147

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Conversation

Heedong0924
Copy link
Collaborator

요구사항

배포

Here

기본

로그인

  • 이메일 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 에 유효한 값을 입력하면 '회원가입' 버튼이 활성화 됩니다.
  • 활성화된 '회원가입' 버튼을 누르면 로그인 페이지로 이동합니다

심화

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

주요 변경사항

  • index .html내 hero 이미지의 background-image 속성을 제거, img태그를 활용해 다시 구현

스크린샷

스크린샷 2025-05-02 170304

스크린샷 2025-05-02 170327

스크린샷 2025-05-02 174142

스크린샷 2025-05-02 174210

멘토에게

  • 미디어 쿼리 관련 피드백에 대해... 이미 데스크톱 화면을 기준으로 작성된 코드를 변경하는 것이 꽤나 힘들고 자꾸 스타일 우선순위때문에 꼬여서... sprint4 먼저 작업하게 되었습니다.
  • 작업 중 뒤로 가기 등으로 인한 입력값 복원이 발생했을 때, 입력값에 대한 검증이 focusout 이벤트로 발생하기 때문에 잘못된 값이 넣어진 상태로 입력값이 복원되더라도 focusout 이벤트가 발생하지 않았습니다.
    저는 window객체의 pageshow 이벤트 리스너를 통해 페이지 실행 시 강제로 focusout 이벤트를 1회 실행시키도록 구현했는데요, 뭔가 좋은 구조라는 느낌은 안 들어서... 입력값 복원을 유지한 채로(input value를 초기화하지 않고) 더 나은 방법이 있는가에 대해 여쭤봅니다.
  • authFormUtils.js 파일에 회원가입이나 로그인에 요구되는 사항들의 함수를 구현해놨습니다. 그런데 changeDetail과 같은 함수는 인자로 event 객체를 받고 있는데요, 이런 구조도 괜찮을까요? 이벤트 객체를 다루는 이 함수가 순수하다는 느낌이 들지 않아서 사이드 이펙트를 발생할 수도 있지 않을까 라는 생각이 조금 듭니다.
  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.

1. Email validation 추가 정규식 활용
2. Password validation 추가
3. 모든 확인 조건이 만족되었을 때, login/# 버튼 활성화 기능 추가
4. Password 표시를 위한 Toggle Btn 추가
@Heedong0924 Heedong0924 requested a review from addiescode-sj May 2, 2025 08:54
@Heedong0924 Heedong0924 added the 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. label May 2, 2025
Copy link
Collaborator

@addiescode-sj addiescode-sj left a comment

Choose a reason for hiding this comment

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

수고하셨습니다!
구조화도 잘하셨고 좋은 시도도 많았는데,
좀 더 유지보수에 유리하고 효율적인 방법은 없을지 코멘트 참고해보시고 더 고민해봅시다 👍

주요 리뷰 포인트

  • 유지보수를 고려한 개발
  • 함수 네이밍


// function
const verifyInputs = () => {
authFormUtils.verify(verifiationList)
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
authFormUtils.verify(verifiationList)
const isValid = authFormUtils.verify(verifiationList)

사소하지만, 이런식으로 변수로 만들어주면 함수 내부를 들여다보지않아도 실행 결과값에 대한 예측이 좀 더 쉬워지겠죠? :)

* 뒤로 가기 등 페이지를 복구했을 때, 브라우저가 입력값을 복원하는 과정에서 요구사항의 focusout 이벤트가 발생하지 않음.
* 따라서, pageshow 이벤트 발생 후 email 값이 있는 경우 (입력값이 복원된 경우) 강제로 focusout 이벤트 실행
*/
window.addEventListener("pageshow", () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

코드들이 일련의 흐름으로 실행된다기보다는 흩어져있어 파악이 어려워보여요.
이벤트리스너의 콜백에 직접적으로 관련 로직을 작성하기보다는 개별 함수로 작업을 분리해주고, 이런식으로 initialize를 담당하는 함수를 하나 만들어보면 어떨까요?

// 페이지 복원 시 폼 상태 검증
const validateFormOnRestore = () => {
  const inputs = [
    { element: inputEmail, detail: detailEmail, field: 'email' },
    { element: inputPw, detail: detailPw, field: 'password' }
  ];
  
  inputs.forEach(({ element, detail, field }) => {
    if (element.value) {
      validateField(element, detail, field);
    }
  });
};

// 이벤트 리스너 설정
const setupEventListeners = () => {
  // 페이지 복원 이벤트
  window.addEventListener('pageshow', validateFormOnRestore);
  
  // 이메일 입력 필드
  inputEmail.addEventListener('focusout', (e) => {
    validateField(e.target, detailEmail, 'email');
  });
  
  // 비밀번호 입력 필드
  inputPw.addEventListener('focusout', (e) => {
    validateField(e.target, detailPw, 'password');
  });
  
  // 비밀번호 표시 토글
  togglePw.addEventListener('click', togglePasswordVisibility);
};

// 초기화
setupEventListeners();

Copy link
Collaborator

Choose a reason for hiding this comment

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

이렇게 작성한다면 코드 중복을 제거하는데도 효과가 있고, 이벤트가 처리되는 흐름을 구조화할수있고, 모든 이벤트 리스너를 한곳에서 관리함으로써 각 이벤트 핸들러가 좀 더 명확한 의도와 역할을 가지고 실행될수있게끔 처리해줄수있겠죠?

})();

// function
const verifyInputs = () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

해당 함수가 하는 역할이 input을 유효성검사하기보다는, 유효성 검사 결과를 button UI state에 반영하는일에 가깝지않을까요?

Comment on lines +40 to +51
const isCorrect = authFormUtils.isCorrectEmail(e.target.value);

if (!e.target.value) {
authFormUtils.changeDetail(e, detailEmail, "이메일을 입력해주세요");
verifiationList.email = false;
} else if (!isCorrect) {
authFormUtils.changeDetail(e, detailEmail, "잘못된 이메일 형식입니다.");
verifiationList.email = false;
} else {
authFormUtils.changeDetail(e, detailEmail);
verifiationList.email = true;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

유효성 검사 규칙에 따른 유효성 검사 결과를 반환하는 형태의 함수가 모듈화되어있지않아 페이지 단위의 js에서 매번 유효성 검사를 수행하기위한 코드 블락을 작성해야하는게 비효율적으로 보여요.

이런식으로 간소화해보면 어떨까요?

예시)

// 유효성 검사 함수들
export const validators = {
  email: (value) => {
    if (!value) return { isValid: false, message: '이메일을 입력해주세요' };
    if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
      return { isValid: false, message: '올바른 이메일 형식이 아닙니다' };
    }
    return { isValid: true, message: '' };
  },

  password: (value) => {
    if (!value) return { isValid: false, message: '비밀번호를 입력해주세요' };
    if (value.length < 8) {
      return { isValid: false, message: '비밀번호는 8자 이상이어야 합니다' };
    }
    return { isValid: true, message: '' };
  }
};

// 입력 필드 검증 함수
const validateField = (inputEl, detailEl, field) => {
  const value = inputEl.value.trim();
  const result = validators[field](value);
  
  if (result.isValid) {
    authFormUtils.changeDetail(inputEl, detailEl);
  } else {
    authFormUtils.changeDetail(inputEl, detailEl, result.message);
  }
  
  updateFormState(field, value, result.isValid);
};

return MIN_PW_LEN <= pw.length;
};

export const changeDetail = (event, detailElement, text = "") => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

함수 이름이 좀 모호하게 느껴져요. 결국 이 함수가 하는 일이 유효성 검사 상태에 따른 UI state 업데이트라면 updateFieldState 정도는 어떨까요?

@addiescode-sj
Copy link
Collaborator

질문에 대한 답변

멘토에게

  • 미디어 쿼리 관련 피드백에 대해... 이미 데스크톱 화면을 기준으로 작성된 코드를 변경하는 것이 꽤나 힘들고 자꾸 스타일 우선순위때문에 꼬여서... sprint4 먼저 작업하게 되었습니다.
  • 작업 중 뒤로 가기 등으로 인한 입력값 복원이 발생했을 때, 입력값에 대한 검증이 focusout 이벤트로 발생하기 때문에 잘못된 값이 넣어진 상태로 입력값이 복원되더라도 focusout 이벤트가 발생하지 않았습니다.
    저는 window객체의 pageshow 이벤트 리스너를 통해 페이지 실행 시 강제로 focusout 이벤트를 1회 실행시키도록 구현했는데요, 뭔가 좋은 구조라는 느낌은 안 들어서... 입력값 복원을 유지한 채로(input value를 초기화하지 않고) 더 나은 방법이 있는가에 대해 여쭤봅니다.
  • authFormUtils.js 파일에 회원가입이나 로그인에 요구되는 사항들의 함수를 구현해놨습니다. 그런데 changeDetail과 같은 함수는 인자로 event 객체를 받고 있는데요, 이런 구조도 괜찮을까요? 이벤트 객체를 다루는 이 함수가 순수하다는 느낌이 들지 않아서 사이드 이펙트를 발생할 수도 있지 않을까 라는 생각이 조금 듭니다.
  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.

그랬군요! 디테일을 볼줄 아시네요 👍
우선 지금과 같이 페이지 실행 시 강제로 focusout 이벤트를 1회 실행시키는것보다는 웹 스토리지 (sessionStorage)를 이용해 입력값을 persist하거나 커스텀 이벤트 만드는 방법이 있을것같아요.

둘중에 더 편한 방법으로 시도해보세요!
나머지 질문은 PR 본문 코멘트로 상세히 답변드렸습니다 :)

@addiescode-sj addiescode-sj merged commit c27992b into codeit-bootcamp-frontend:Basic-김동희 May 14, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants