Skip to content
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

[함헌규] sprint3 #34

Merged

Conversation

heonq
Copy link
Collaborator

@heonq heonq commented Oct 6, 2024

스프린트 미션 3 요구사항

로그인, 회원가입 페이지 공통

기본 요구사항

  • 로그인 및 회원가입 페이지의 이메일, 비밀번호, 비밀번호 확인 input에 필요한 유효성 검증 함수를 만들고 적용해 주세요.
  • 이메일 input에서 focus out 할 때, 값이 없을 경우 input에 빨강색 테두리와 아래에 “이메일을 입력해주세요.” 빨강색 에러 메세지를 보입니다.
  • 이메일 input에서 focus out 할 때, 이메일 형식에 맞지 않는 경우 input에 빨강색 테두리와 아래에 “잘못된 이메일 형식입니다” 빨강색 에러 메세지를 보입니다.
  • 비밀번호 input에서 focus out 할 때, 값이 없을 경우 아래에 “비밀번호를 입력해주세요.” 에러 메세지를 보입니다
  • 비밀번호 input에서 focus out 할 때, 값이 8자 미만일 경우 아래에 “비밀번호를 8자 이상 입력해주세요.” 에러 메세지를 보입니다.
  • input 에 빈 값이 있거나 에러 메세지가 있으면 ‘로그인’ 버튼은 비활성화 됩니다.
  • Input 에 유효한 값을 입력하면 ‘로그인' 버튼이 활성화 됩니다.
  • 활성화된 ‘로그인’ 버튼을 누르면 “/items” 로 이동합니다

심화 요구사항

  • 브라우저에 현재 보이는 화면의 영역(viewport) 너비를 기준으로 분기되는 반응형 디자인을 적용합니다. (참고: https://www.codeit.kr/topics/responsive-web-publishing)
  • PC: 1200px 이상
  • Tablet: 744px 이상 ~ 1199px 이하
  • Mobile: 375px 이상 ~ 743px 이하
  • 375px 미만 사이즈의 디자인은 고려하지 않습니다.
  • Tablet 사이즈에서 내부 디자인은 PC사이즈와 동일합니다.
  • Mobile 사이즈에서 좌우 여백 16px 제외하고 내부 요소들이 너비를 모두 차지합니다.
  • Mobile 사이즈에서 내부 요소들의 너비는 기기의 너비가 커지는 만큼 커지지만 400px을 넘지 않습니다.
  • 비밀번호 및 비밀번호 확인 입력란에 눈 모양 아이콘 클릭 시 비밀번호 표시/숨기기 토글이 가능합니다. 기본 상태는 비밀번호 숨김으로 설정합니다.

로그인 페이지

기본 요구사항

  • 이메일과 비밀번호를 입력하고 로그인 버튼을 누른 후, 다음 조건을 참조하여 로그인 성공 여부를 alert 메시지로 출력합니다.
  • 만약 입력한 이메일이 데이터베이스(USER_DATA)에 없거나, 이메일은 일치하지만 비밀번호가 틀린 경우, '비밀번호가 일치하지 않습니다.'라는 메시지를 alert로 표시합니다
  • 만약 입력한 이메일이 데이터베이스에 존재하고, 비밀번호도 일치할 경우, “/items”로 이동합니다.

심화 요구사항

  • 오류 메시지 모달을 구현합니다. 모달 내 내용은 alert 메시지와 동일합니다.

회원가입 페이지

기본 요구사항

  • 회원가입을 위해 이메일, 닉네임, 비밀번호, 비밀번호 확인을 입력한 뒤, 회원가입 버튼을 클릭하세요. 그 후에는 다음 조건에 따라 회원가입 가능 여부를 alert로 알려주세요.
  • 입력한 이메일이 이미 데이터베이스(USER_DATA)에 존재하는 경우, '사용 중인 이메일입니다'라는 메시지를 alert로 표시합니다.
  • 입력한 이메일이 데이터베이스(USER_DATA)에 없는 경우, 회원가입이 성공적으로 처리되었으므로 로그인 페이지(”/login”)로 이동합니다.

심화 요구사항

  • 오류 메시지 모달을 구현합니다. 모달 내 내용은 alert 메시지와 동일합니다.

랜딩 페이지

심화 요구사항

  • 브라우저에 현재 보이는 화면의 영역(viewport) 너비를 기준으로 분기되는 반응형 디자인을 적용합니다. (참고: https://www.codeit.kr/topics/responsive-web-publishing)
    • PC: 1200px 이상
    • Tablet: 744px 이상 ~ 1199px 이하
    • Mobile: 375px 이상 ~ 743px 이하
    • 375px 미만 사이즈의 디자인은 고려하지 않습니다.
  • PC, Tablet 사이즈의 이미지 크기는 고정값을 사용합니다.
  • Mobile 사이즈의 이미지는 좌우 여백 32px을 제외하고 이미지 영역이 꽉 차게 구현합니다. (이때 가로가 커지는 비율에 맞춰 세로도 커져야 합니다.)
  • Tablet 사이즈로 작아질 때 최소 좌우 여백이 “판다마켓” 로고의 왼쪽에 여백 24px, “로그인” 버튼 오른쪽 여백 24px을 유지할 수 있도록 “판다마켓” 로고와 “로그인" 버튼의 간격이 가까워집니다.
  • Mobile 사이즈로 작아질 때 최소 좌우 여백이 “판다마켓” 로고의 왼쪽에 여백 16px, “로그인” 버튼 오른쪽 여백 16px을 유지할 수 있도록 “판다마켓” 로고와 “로그인" 버튼의 간격이 가까워집니다.
  • Mobile 사이즈 너비가 커지면, “Privacy Policy”, “FAQ”, “codeit-2023”이 있는 영역과 SNS 아이콘들이 있는 영역의 사이 간격이 커집니다.
  • 페이스북, 카카오톡, 디스코드, 트위터 등 SNS에서 판다마켓 랜딩 페이지(“/”) 공유 시 미리보기를 볼 수 있도록 랜딩 페이지 메타 태그를 설정합니다.
  • 미리보기에서 제목은 “판다마켓”, 설명은 “일상에서 모든 물건을 거래해보세요”로 설정합니다.
  • 주소와 이미지는 자유롭게 설정하세요.
  • 로그인, 회원가입 페이지에 공통으로 사용하는 로직이 있다면, 반복하지 않고 공통된 로직을 모듈로 분리해 사용해 주세요.

주요 변경사항

  • 로그인/회원가입 페이지의 input창에서 focusout할 때 유효하지 않은 값이 입력됐을 경우
  • 로그인 시 데이터베이스에 있는 계정 정보와 일치하지 않을 경우 에러 메시지 모달 표시
  • 회원가입 시 데이터베이스에 있는 계정과 중복될 경우 에러 메시지 모달 표시
  • 데스크탑,태블릿,모바일 등 사이즈에 따른 반응형 디자인 구현

스크린샷

로그인 페이지 반응형

login_375px

회원가입 페이지 반응형

signup_375px

랜딩페이지 반응형

landing_375px

에러메시지

login_error_modal
login_input_message
signup_input_message

멘토에게

  • 커밋 메시지는 어느정도로 구체적으로 작성하는 것이 좋은지 기준이 궁금합니다.
  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.

- 문제가 없을 시  메시지를 반환하도록 수정
- 로그인 성공 시 items 경로로 이동
- Object.keys를 통해 상태의 이름을 가져오도록 수정
- 로그인/회원가입 버튼 클릭 시 데이터베이스의 아이디와 비교 후 처리:
로그인의 경우 데이터베이스에 존재하는 이메일과 비밀번호를 입력할 경우 items 페이지로 이동
회원가입의 경우 데이터베이스에 존재하는 이메일과 일치하지 않는 경우 items 페이지로 이동
이에 해당하지 않을 경우 alert로 메시지를 표시

- 로그인과 회원가입에 중복되는 로직을 하나의 클래스로 구현하고 이를 extend하도록 설정:
로그인과 회원가입에서 차이가 있는 로직은 각자 클래스에서 구현
- 비밀번호 입력창 옆에 눈 아이콘을 클릭하면 비밀번호 표시 여부를 토글하는 기능 구현
- sign클래스에 input요소의 값을 가져오는 getValues 메소드 구현

- 프로퍼티의 키에 사용되는 문자열을 KEYS 객체를 생성해서 입력
- 기존에 first,second,third 클래스로 참조하던 방식을 nth-of-type으로 참조하도록 변경
- 기존에 함수로 구현했던 기능을 sign 클래스에 추가하고 이를 사용하도록 수정

- 에러 메시지를 숨길 때 aria-hidden 속성을 true로 변경
@heonq heonq requested a review from kimjong95 October 6, 2024 04:49
@heonq heonq self-assigned this Oct 6, 2024
@heonq heonq added 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. 최종 제출 스프린트미션 최종 제출본입니다. labels Oct 6, 2024
if (message.length) {
e.target.classList.add("error");
errorMessageNode.setAttribute("aria-hidden", false);
return errorMessageNode.classList.add("show");
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

특정 요소에 display:none으로 설정 후 show클래스에 display:block을 설정해서 요소를 표시할 때 show 클래스를 추가하는 식으로 구현했는데
해당 요소는 p 요소라 innerText를 빈 문자열로 설정해서 안보이게 했다가 innerText에 메시지를 입력해서 표시 할 수 있을 것 같은데 둘 중 어떤 방식이 바람직한지 궁금합니다!

Copy link
Collaborator

Choose a reason for hiding this comment

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

방식은 여러가지가 있을수 있겠으나 에러메세지가 있거나, 없거나를 생각한다면 innerText를 빈문자열로, 혹은 에러메세지로 설정해서 표시해주시는게 좋을것 같아요! 현재는 error를 보여주는 텍스트의 레이아웃(크기)이 잡혀있기에 이런식으로 처리해도 무방할 것 같습니다

[KEYS.password]: $("#password"),
};
this.validateMethods = [validator.validateEmail, validator.validatePassword];
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

입력창 DOM 요소와 입력창의 값에 대한 유효성 검사 함수를 이렇게 배열형태로 필드로 저장하고 사용하는 방식은 적절한 방식인지 궁금합니다!

Copy link
Collaborator

Choose a reason for hiding this comment

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

작성해주신대로 어떠한 비즈니스로직을 구성할 때 미리 필요한 항목들을 배열형태로 작성하는 방식은 많이 사용하는 방식입니다! 그리고 KEYS.email, KEYS.password처럼 명시적인 이름을 붙혀주셧기에 확인하기도 쉬울 것 같아요.

하지만 이러한 경우의수가 굉장히 많을때는 조금 경계해야 할 필요도 있습니다. 성능상의 문제가 발생하거나, 잘 작성된 주석이 없다면 다른사람이 코드를 읽기 불편한 상황이 생길수 있습니다.
그 예로 위에 Sign클래스의 setInput함수를 보면 배열의 인덱스 순으로 값을 검증하는걸 볼 수 있는데, 이럴때 순서에 의해서도 오류가 발생할 수도 있습니다. 따라서 각각의 필드를 따로 관리하거나, 다른 자료구조를 사용해 볼 수 있다면 이러한 문제를 해결할 수도 있을것 같아요.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

동일한 key를 가진 객체형태로 변경하고 key를 통해 참조하도록 변경했습니다!

Copy link
Collaborator

@kimjong95 kimjong95 left a comment

Choose a reason for hiding this comment

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

전체적으로 정말 잘 작성해주신 코드 같습니다.
변수명, 함수명에 조금 더 신경을 써주시면 좋을것 같습니다.

현재는 js파일들이 모두 html이벤트를 잡아서 처리하게 되어있는데 혹시 의도하신걸까요?
이럴때의 장점은 js와 html, css가 모두 모듈화가 되기때문에 서로의 관심사에대하여 분리하여 작성되어 관리의 측면에서 이득이 생길 수 있습니다. 반면 복잡해지는 컨텍스트가 발생한다면 추적이 어려울 수도 있을것 같아요.
반대로 html에서 js에서 선언한 함수들, 객체들을 바로 사용하는 방법도 있을수 있는데 이는 반대로 컨텍스트가 복잡해도 연결해서 보기 쉽지만 관심사의 분리가 어려운 단점을 가지고 있기도 합니다.

커밋메세지의 내용은 그 커밋이 어떠한 변경사항을 나타내고있는지 보여주면 됩니다. 지금도 잘 쪼개주셨고, 잘 작성해주신걸로 확인됩니다. prefix도 잘 사용해주시고 있기도 하고요!

if (message.length) {
e.target.classList.add("error");
errorMessageNode.setAttribute("aria-hidden", false);
return errorMessageNode.classList.add("show");
Copy link
Collaborator

Choose a reason for hiding this comment

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

방식은 여러가지가 있을수 있겠으나 에러메세지가 있거나, 없거나를 생각한다면 innerText를 빈문자열로, 혹은 에러메세지로 설정해서 표시해주시는게 좋을것 같아요! 현재는 error를 보여주는 텍스트의 레이아웃(크기)이 잡혀있기에 이런식으로 처리해도 무방할 것 같습니다

errorMessageNode.classList.remove("show");
}

setInputs() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

함수이름은 setInputs인데 구현내부는 focusout 이벤트에 대하여 리스너를 추가하고, 내부 내용이 구현되어있는것 같아요.
함수명이 좀더 명확하면 좋을것 같아요

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

함수명을 handleInputFocusout 으로 변경했습니다!

import $ from "../utils/query.js";

class Sign {
constructor() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

생성자에서 만들어주신 class 내부 각 필드들이 어떠한 역활을 하는지 주석으로 적어주시면 좋을것 같아요

const input = target.closest("div").querySelector("input");
const TYPES = ["text", "password"];
const inputType = input.type;
input.type = TYPES[Number(inputType === TYPES[0])];
Copy link
Collaborator

Choose a reason for hiding this comment

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

현재 password input의 type이 text인지, pasword인지 확인한 값을 숫자 0, 1 로 관리하는걸로 보면 될까요?
직관적으로 작성해주셔도 될것 같아요. 위에 TYPES로 선언해놓으신 값의 의미를 제가 이해하지못한것 같아요.
아니면 다른 의도가 있으신걸까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

다시 보니 정말 직관적이지 않은 것 같습니다.
input.type === "text" ? (input.type = "password") : (input.type = "text");로 변경했습니다!

[KEYS.password]: $("#password"),
};
this.validateMethods = [validator.validateEmail, validator.validatePassword];
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

작성해주신대로 어떠한 비즈니스로직을 구성할 때 미리 필요한 항목들을 배열형태로 작성하는 방식은 많이 사용하는 방식입니다! 그리고 KEYS.email, KEYS.password처럼 명시적인 이름을 붙혀주셧기에 확인하기도 쉬울 것 같아요.

하지만 이러한 경우의수가 굉장히 많을때는 조금 경계해야 할 필요도 있습니다. 성능상의 문제가 발생하거나, 잘 작성된 주석이 없다면 다른사람이 코드를 읽기 불편한 상황이 생길수 있습니다.
그 예로 위에 Sign클래스의 setInput함수를 보면 배열의 인덱스 순으로 값을 검증하는걸 볼 수 있는데, 이럴때 순서에 의해서도 오류가 발생할 수도 있습니다. 따라서 각각의 필드를 따로 관리하거나, 다른 자료구조를 사용해 볼 수 있다면 이러한 문제를 해결할 수도 있을것 같아요.

import { validator } from "./utils/validator.js";
import { KEYS } from "./constants/names.js";

class LoginForm extends Sign {
Copy link
Collaborator

Choose a reason for hiding this comment

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

상속을 이용해서 처리해주신 부분 굉장히 좋은것 같습니다!

});
}

getValues() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

아래 리뷰하다가 다시 돌아왔는데,

입력필드의 어떠한 값을 가져올때 항상 전체를 가져와서 하나를 사용하는식으로 사용될것 같아요.
현재는 배열 형태로 구성하고 있지만 이럴때 key, value쌍으로 저장되어있는 자료구조를 사용한다면 특정 값만 접근하는 방법을 사용할 수도 있을것 같습니다.

if (password !== confirmPassword) return ERROR_MESSAGES.passwordNotMatch;
return "";
},
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

파일전체적으로, 정규식을 통해서 값을 검증하는것, 얼리리턴 사용해주신것, 에러의 메세지를 상수값으로 미리 선언해두신것 모두 좋은것 같습니다.

onSubmit() {
const values = this.getValues();
const matchingAccount = USER_DATA.find((data) => data.email === values.email);
matchingAccount
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 Author

Choose a reason for hiding this comment

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

submit 성공,실패 함수를 추가했습니다. 감사합니다!

Copy link
Collaborator

@kimjong95 kimjong95 left a comment

Choose a reason for hiding this comment

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

크리티컬한 내용이 없는것 같아서 Approve 해두겠습니다.

@kimjong95 kimjong95 merged commit da5b98a into codeit-sprint-fullstack:basic-함헌규 Oct 13, 2024
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