-
Notifications
You must be signed in to change notification settings - Fork 26
[김원선]sprint4 #80
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
[김원선]sprint4 #80
The head ref may contain hidden characters: "Basic-\uAE40\uC6D0\uC120-sprint4"
Conversation
fix : 오타로 인한 버그 수정, 스타일 추가 fix : 오타로 인한 버그 수정2 fix : 토글 오류 해결
|
스프리트 미션 하시느라 수고 많으셨어요. |
|
굿굿 ! 커밋이 정말 깔끔하네요 👍 |
| --Secondary400: #9ca3af; | ||
| --Secondary800: #1f2937; | ||
| --gray900: #111827; |
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.
(제안) 컬러 팔레트 변수명도 일관성있는 컨벤션으로 작성하는게 어떨까요 ? 😉
| --Secondary400: #9ca3af; | |
| --Secondary800: #1f2937; | |
| --gray900: #111827; | |
| --secondary400: #9ca3af; | |
| --secondary800: #1f2937; | |
| --gray900: #111827; |
| <meta property="og:image" content="/image/Landing_Page_img.png" /> | ||
| <meta property="og:url" content="http://pandamakert.netlify.app" /> |
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.
굿굿 ! 메타 태그를 적절하게 수정하셨군요 ! 👍
| <meta property="og:image" content="/image/Landing_Page_img.png" /> | |
| <meta property="og:url" content="http://pandamakert.netlify.app" /> | |
| <meta property="og:image" content="/image/Landing_Page_img.png" /> | |
| <meta property="og:url" content="https://pandamakert.netlify.app" /> |
그런데 프로토콜에 s가 빠진 것 같아요 !
물론 http로 접근해도 리다이렉트(https로) 되긴 하겠으나 정확한 URL이 더 낫겠죠 ?😊
| form.addEventListener("submit", (e) => { | ||
| e.preventDefault(); | ||
| window.location.href = "/item"; | ||
| }); |
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.
크으 ~ 제출 이벤트 리스너를 추가하셨군요 ! 👍
이벤트 객체를 활용한 e.preventDefault();도 너무 좋습니다 !
제출에 이벤트 리스너를 추가하면 접근성은 물론이고 브라우저의 기본 사용자 경험인 엔터나 제출 버튼 클릭 모두 유효하겠어요 👍
| function emailCheck(value) { | ||
| const emailRegex = | ||
| /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i; | ||
|
|
||
| return emailRegex.test(value); | ||
| } |
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.
함수 이름은 동사로 짓는게 어떨까요?
| function emailCheck(value) { | |
| const emailRegex = | |
| /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i; | |
| return emailRegex.test(value); | |
| } | |
| function checkEmail(value) { // 혹은 validateEmail | |
| const emailRegex = | |
| /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i; | |
| return emailRegex.test(value); | |
| } |
일반적으로 변수는 명사, 함수는 동사로 지어요.
boolean의 경우 isValidEmail와 같이 is, are, has로 시작하기도 합니다. =)
함수의 경우 다음과 같은 단어들이 접두사가 될 수 있어요:
- get
- fetch
- push
- update
- create
- calculate
- set
- 등등 ...
| function emailCheck(value) { | ||
| const emailRegex = | ||
| /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i; | ||
|
|
||
| return emailRegex.test(value); | ||
| } |
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.
크으 ~ 순수 함수를 구현하시다니 👍
해당 함수는 입력값(email)이 같으면 언제나 같은 결과(true/false)를 반환하고 외부 상태에 영향을 주거나 의존하지도 않아요.
이런 함수를 “순수 함수(Pure Function)” 라고 부릅니다.
이러한 구조는 테스트하기도 쉽고, 예측 가능한 코드 작성에 도움이 되는 좋은 패턴입니다.
지금처럼 유틸리티 함수를 순수하게 분리해 작성하는 습관, 정말 잘 하고 계세요! 🔥
| function activeButton() { | ||
| if (emailCheck(userEmail.value) && userPassword.value.length >= 8) { | ||
| submitButton.disabled = false; | ||
| } else { | ||
| submitButton.disabled = true; | ||
| } | ||
| } |
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.
다음과 같이 작성해볼 수 있을 것 같아요 !
| function activeButton() { | |
| if (emailCheck(userEmail.value) && userPassword.value.length >= 8) { | |
| submitButton.disabled = false; | |
| } else { | |
| submitButton.disabled = true; | |
| } | |
| } | |
| function activeButton() { | |
| const isValidEmail = emailCheck(userEmail.value) && userPassword.value.length >= 8; | |
| submitButton.disabled = isValidEmail; | |
| } |
이렇게 하면 별칭(isValidEmail)으로 인해 가독성도 좋아지고, 조건 분기를 사용하지 않고 조건 자체를 값으로 대입해 볼 수 있어요 !
| export const errMsg = { | ||
| id: { | ||
| voidOut: "이메일을 입력해주세요.", | ||
| fail: "잘못된 이메일 형식입니다.", | ||
| }, | ||
| name: { | ||
| fail: "닉네임을 입력해주세요.", | ||
| }, | ||
| pw: { | ||
| voidOut: "비밀번호를 입력해주세요.", | ||
| fail: "비밀번호를 8자 이상 입력해주세요.", | ||
| }, | ||
| rePw: "비밀번호가 일치하지 않습니다.", | ||
| }; |
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.
(심화) 오오...... 에러 메시지를 구조적인 설계로 접근하셨네요 ..? 🫢
좀 더 응용하면 스키마로 만들 수도 있겠는데요?
스키마: 어떤 구조로 데이터가 저장되는가를 나타내는 구조
예를 들어서 다음과 같이:
| export const errMsg = { | |
| id: { | |
| voidOut: "이메일을 입력해주세요.", | |
| fail: "잘못된 이메일 형식입니다.", | |
| }, | |
| name: { | |
| fail: "닉네임을 입력해주세요.", | |
| }, | |
| pw: { | |
| voidOut: "비밀번호를 입력해주세요.", | |
| fail: "비밀번호를 8자 이상 입력해주세요.", | |
| }, | |
| rePw: "비밀번호가 일치하지 않습니다.", | |
| }; | |
| export const validationSchema = { | |
| id: { | |
| validate: (value) => !!value && /^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/.test(value), | |
| message: { | |
| voidOut: "이메일을 입력해주세요.", | |
| fail: "잘못된 이메일 형식입니다.", | |
| }, | |
| }, | |
| name: { | |
| validate: (value) => !!value, | |
| message: { | |
| fail: "닉네임을 입력해주세요.", | |
| }, | |
| }, | |
| pw: { | |
| validate: (value) => !!value && value.length >= 8, | |
| message: { | |
| voidOut: "비밀번호를 입력해주세요.", | |
| fail: "비밀번호를 8자 이상 입력해주세요.", | |
| }, | |
| }, | |
| rePw: { | |
| validate: (value, originalPw) => value === originalPw, | |
| message: "비밀번호가 일치하지 않습니다.", | |
| }, | |
| }; |
이렇게 확장해서 구성해볼 수도 있겠어요 !
접근 방법이 좋으셔서 심화 인사이트도 드려봅니다 ! 😉
| function emailCheck(value) { | ||
| const emailRegex = | ||
| /^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/i; | ||
|
|
||
| return emailRegex.test(value); | ||
| } |
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.
해당 함수는 signin.js에도 이미 존재하는군요 !
중복된 로직이 있으면 점점 복잡해질 수 있어요. 여러 페이지에서 비슷한 기능을 하는 코드들이 반복되고 있다면?
로그인, 회원가입 등 페이지마다 공통적인 유효성 검사나 동작이 존재하는 경우가 많습니다.
이러한 로직을 각 JS 파일에 그때그때 작성하게 되면 아래와 같은 문제가 생길 수 있어요:
- 로직 수정 시, 모든 파일을 수정해야 해요.
- 서로 약간씩 다른 방식으로 유사한 로직을 구현하게 되면 버그 발생 가능성이 증가합니다.
- 공통 로직의 변화가 전체 페이지에 ripple effect(연쇄 영향)를 줄 수 있어요.
이처럼 중복된 코드가 많아질수록, 전체 프로젝트의 유지보수 비용은 계속 높아지게 됩니다.
그렇다면 어떻게 할까?
그렇다면 어떻게 할 수 있을까요?
재사용이 필요한 로직은 별도 모듈로 분리해서 관리하고,
각 페이지는 해당 모듈을 가져와 사용하는 방식으로 구성해보는 건 어떨까요?
// validate.js
export function isValidEmail(email) { ... }
export function isValidPassword(password) { ... }// sign-in.js
import { isValidEmail } from './validate.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 파일에도 가서 고쳐야 하네?"
- "이 기능이 특정 페이지에만 종속되지 않아!"
어떻게 하면 더 나은 설계를 할 수 있을까?”를 고민하는 건 아주 중요한 개발자의 태도예요.
정답은 없지만, 재사용성과 유지보수성이라는 기준을 계속 떠올리면서 코드를 분리하는 연습을 하다 보면,
더욱 확장성 있는 구조를 만들 수 있게 됩니다.
|
크으 ~ 접근 방법이 너무 좋으셨습니다. 이번 미션 수행하시느라 정말 수고 많으셨고 다음 미션도 기대해볼게요 원선님 ! |
요구사항
배포주소: https://pandamakert.netlify.app/
Github에 PR(Pull Request)을 만들어서 미션을 제출합니다.
피그마 디자인에 맞게 페이지를 만들어 주세요.
React와 같은 UI 라이브러리를 사용하지 않고 진행합니다.
기본
로그인
회원가입
심화
주요 변경사항
스크린샷
멘토에게