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

[이해빈] Week13 #406

Merged

Conversation

lhv0829
Copy link
Collaborator

@lhv0829 lhv0829 commented Jan 16, 2024

요구사항

기본

12주차

  • Input 컴포넌트에 값이 없는 경우 회색의 placeholder값을 볼 수 있나요?
  • Input 컴포넌트에 focus in 하면 파랑색 테두리를 볼 수 있나요?
  • Input 컴포넌트에 눈 모양 아이콘을 누르면 비밀번호 가리기/보기 기능이 토글 되나요?
  • Input 컴포넌트에 값이 에러케이스일 경우 빨강색 테두리와 에러 메세지를 볼 수 있나요?
  • Input 컴포넌트에서 focus out 하면 실행할 함수를 설정할 수 있나요?

13주차

  • [로그인 페이지] “회원 가입하기”를 클릭하면 ‘/signup’ 페이지로 이동하나요?
  • [로그인 페이지] 이메일 input에 placeholder는 “이메일을 입력해 주세요.”, 비밀번호 input에 placeholder는 “비밀번호를 입력해 주세요.”가 보이나요?
  • [로그인 페이지] 이메일 input에서 focus out 할 때, 값이 없을 경우 아래에 “이메일을 입력해주세요.” 에러 메세지가 보이나요?
  • [로그인 페이지] 이메일 input에서 focus out 할 때, 이메일 형식에 맞지 않는 값이 있는 경우 아래에 “올바른 이메일 주소가 아닙니다.” 에러 메세지가 보이나요?
  • [로그인 페이지] 비밀번호 input에서 focus out 할 때, 값이 없을 경우 아래에 “비밀번호를 입력해주세요.” 에러 메세지가 보이나요?
  • [로그인 페이지] 로그인 실패하는 경우, 이메일 input 아래에 “이메일을 확인해주세요.”, 비밀번호 input 아래에 “비밀번호를 확인해주세요.” 에러 메세지가 보이나요?
  • [로그인 페이지] 로그인 버튼 클릭 또는 Enter키 입력으로 로그인 실행 되나요?
  • [로그인 페이지] https://bootcamp-api.codeit.kr/docs 에 명세된 “/api/sign-in”으로 { “email”: “[email protected]”, “password”: “sprint101” } POST 요청해서 성공 응답을 받으면 “/folder”로 이동하나요?
  • [회원가입 페이지] “로그인 하기”를 클릭하면 ‘/signin’ 페이지로 이동하나요?
  • [회원가입 페이지] 이메일 input에 placeholder는 “이메일을 입력해 주세요.”, 비밀번호 input에 placeholder는 “영문, 숫자를 조합해 8자 이상 입력해 주세요. ”비밀번호 확인 input에 placeholder는 “비밀번호와 일치하는 값을 입력해 주세요.”가 보이나요?
  • [회원가입 페이지] 이메일 input에서 focus out 할 때, 값이 없을 경우 “이메일을 입력해주세요.” 에러 메세지가 보이나요?
  • [회원가입 페이지] 이메일 input에서 focus out 할 때, 이메일 형식에 맞지 않는 값이 있는 경우 “올바른 이메일 주소가 아닙니다.” 에러 메세지가 보이나요?
  • [회원가입 페이지] 비밀번호 input에서 focus out 할 때, 값이 8자 미만으로 있거나 문자열만 있거나 숫자만 있는 경우, “비밀번호는 영문, 숫자 조합 8자 이상 입력해 주세요.” 에러 메세지가 보이나요?
  • [회원가입 페이지] 비밀번호 input과 비밀번호 확인 input의 값이 다른 경우, 비밀번호 확인 input 아래에 “비밀번호가 일치하지 않아요.” 에러 메세지가 보이나요?
  • [회원가입 페이지] 회원가입을 실행할 경우, 문제가 있는 경우 문제가 있는 input에 에러 메세지가 보이나요?
  • [회원가입 페이지] 회원가입 버튼 클릭 또는 Enter키 입력으로 회원가입 실행 되나요?
  • [회원가입 페이지] 이메일 중복 확인은 “/api/check-email” POST 요청해서 확인 할 수 있나요?
  • [회원가입 페이지] 유효한 회원가입 형식의 경우 “/api/sign-up” POST 요청하고 성공 응답을 받으면 “/folder”로 이동하나요?
  • [로그인, 회원가입 페이지 공통] 눈 모양 아이콘 클릭시 비밀번호의 문자열이 보이기도 하고, 가려지나요?
  • [로그인, 회원가입 페이지 공통] 비밀번호의 문자열이 가려질 때는 눈 모양 아이콘에는 사선이 그어져있고, 비밀번호의 문자열이 보일 때는 사선이 없는 눈 모양 아이콘이 보이나요?
  • [로그인, 회원가입 페이지 공통] 소셜 로그인에 구글 아이콘 클릭시 ‘https://www.google.com’, 카카오 아이콘 클릭시 ‘https://www.kakaocorp.com/page’로 이동하나요?
  • [로그인, 회원가입 페이지 공통] 로그인/회원가입시 성공 응답으로 받은 accessToken을 로컬 스토리지에 저장하나요?
  • [로그인, 회원가입 페이지 공통] 로그인/회원가입 페이지에 접근시 로컬 스토리지에 accessToken이 있는 경우 ‘/folder’ 페이지로 이동하나요?

심화

  • 로그인, 회원가입 기능에 react-hook-form을 활용해 주세요.

주요 변경사항

  • folder 페이지 마이그레이션
  • Signin 페이지 생성
  • Signup 페이지 생성

스크린샷

멘토에게

  • 아직 진행중입니다. 하면서 질문 추가하겠습니다.
  • 컴포넌트만 구현되어 있고 props나 기능 추가는 아직 하지 않았습니다.
  • 비밀번호 input을 공통 컴포넌트로 만들어서 사용하려고 하였으나 유효성 함수나 받는 props가 달라 분리하게 되었습니다. 제가 생각했을 때는 둘이 하는 일이 다르다고 느껴졌습니다. 일반 비밀번호 input은 그냥 비밀번호를 입력하고 형식이 맞는지 확인하는 것이고 비밀번호 확인 input은 비밀번호 input에서 받은 값을 넘겨받아 값의 일치여부를 판단하는 일을 하기 때문에 다르다고 생각했습니다. 그래서 별도로 분리하게 되었는데 이게 맞는 건가요? 아니면 둘이 공통 컴포넌트로 만든 다음에 isValidate prop 같은 걸로 유효성 함수를 별도로 받고 입력한 비밀번호를 받는 props를 선택적으로 입력할 수 있도록 해서 하나요?
  • 솔직히 로그인 페이지와 회원가입 페이지에서의 비밀번호 input도 분리되어야 할 것 같다는 생각이 들었습니다. 로그인할 때 비밀번호가 어떤 형식으로 입력해야 하는지 알려주는 곳은 많이 못봐서요..

@lhv0829 lhv0829 added 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. 미완성 죄송합니다... labels Jan 16, 2024
@lhv0829 lhv0829 requested a review from clianor January 16, 2024 18:34
@@ -3,6 +3,7 @@ module.exports = {
content: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
"./src/**/Components/**/*.{js,ts,jsx,tsx}"
Copy link
Collaborator

@clianor clianor Jan 19, 2024

Choose a reason for hiding this comment

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

tailwind.config.js 파일 내의 content는 Tailwind CSS 클래스가 포함된 경로나 파일을 지정하는 역할을 합니다.
이때 정규 표현식을 사용하여 지정된 경로나 파일을 포함시키게 됩니다.
그리고 정규 표현식에서 "./pages/**/*.{js, ts, jsx, tsx}"를 이용해 의미를 설명하고 content 내부를 수정해 보겠습니다.

  1. ./page 현재 디렉토리의 pages 폴더를 가리킴.
  2. ** 모든 하위 디렉토리를 의미하며, pages 폴더 아래의 모든 디렉토리를 의미함.
  3. *.{js, ts, jsx, tsx} js, ts, jsx, tsx 중 하나의 확장자를 가진 파일을 의미함.

이를 통해 content 내부를 수정해 보겠습니다.

content: [
  "./pages/**/*.{js,ts,jsx,tsx}", 
  "./src/**/*.{js,ts,jsx,tsx}"
],

위 코드처럼 작성하시거나 아래처럼 작성해 주시면 됩니다.

content: [
  "./{pages,src}/**/*.{js,ts,jsx,tsx}"
]

Copy link
Collaborator

Choose a reason for hiding this comment

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

https://tailwindcss.com/docs/adding-custom-styles#adding-base-styles

위 문서를 참고해서 기본 스타일을 추가하는 경우 base layer를 사용해 보도록 해보세요.
layer를 사용하면 CSS의 우선순위 문제를 해결하는 데 도움이 됩니다.
CSS는 기본적으로 나중에 선언된 스타일이 우선 적용이 되지만 layer를 사용하면 그러한 문제를 해결하는 데 도움을 줄 수 있습니다.

아래의 글들을 참고해서 css layer에 대한 개념을 학습해 보시면 앞으로 많은 도움이 되실 것 같습니다.

https://medium.com/appwrite-io/css-layers-for-css-resets-f60f270aa1cd
https://developer.mozilla.org/en-US/docs/Web/CSS/@layer

Copy link
Collaborator

@clianor clianor Jan 19, 2024

Choose a reason for hiding this comment

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

추가로 tailwind에 기본적으로 제공되는 3가지 레이어에 대해 설명드리겠습니다.

  1. base: 기본 스타일을 재설정하거나, HTML 요소에 대한 기본 스타일을 설정합니다.
  2. components: 재사용 가능한 클래스 패턴을 정의합니다.
  3. utilities: Tailwind CSS의 유틸리티 클래스를 생성합니다.

작성하는 스타일의 특성에 따라 각각의 레이어에 작성해주시는게 좋습니다.

Copy link
Collaborator

@clianor clianor left a comment

Choose a reason for hiding this comment

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

일반적으로 컴포넌트를 제외한 경로에 대문자를 사용하지 않습니다.
src의 하위 경로들 중에서 components가 Components로 대문자로 시작하는데 추후 소문자로 수정해 주시는 게 좋을 것 같습니다.
운영체제에 따라 파일 시스템이 다르기 때문에 대소문자 관련 이슈가 생길 수 있기에 이런 부분은 통일해 주시는 게 좋습니다.

const CardSection = ({links} : {links:LinkType[]}) => {
return(
<section className={style['card--section']}>
{links?.map((link) => <LinkCard key={link.id} link={link} />)}
Copy link
Collaborator

Choose a reason for hiding this comment

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

지금 links는 타입을 확인했을 때 필수 값으로 보입니다.
links에 값이 없을 때 에러를 방지하고자 옵셔널 체이닝을 사용하셨지만 현재 links는 LinkType[]으로 명시되어 있습니다.
이런 경우에 옵셔널 체이닝을 제거하시는게 좋을 것 같습니다.

<div className={style['info']}>
<p className={style['copyright']}>©codeit - 2023</p>
<div className={style['privacy-faq']}>
<a href="./privacy.html" className={style['privacy']}>Privacy Policy</a>
Copy link
Collaborator

Choose a reason for hiding this comment

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

a 태그가 아니라 next의 link를 사용하도록 개선해 주세요.
a 태그를 직접적으로 사용하시게 된다면 next의 link가 지원하는 기능들을 사용하실 수 없습니다.

Copy link
Collaborator

@clianor clianor left a comment

Choose a reason for hiding this comment

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

훅을 선언하실 때 네이밍을 modalHooks와 같은 네이밍을 선호하시는 것 같습니다.
hooks 디렉토리에 있기 때문에 hooks라는 것을 굳이 파일 명에서 드러내지 않아도 될 것 같습니다.
그리고 훅의 경우 함수 명이 use로 시작하듯이 파일명 역시 useModal과 같이 작성해 주시는 게 일반적입니다.

@@ -1,11 +1,11 @@
import style from '../styles/AddLinkForm.module.css';
import style from './AddLinkForm.module.css';
Copy link
Collaborator

Choose a reason for hiding this comment

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

css module을 사용할 때 보통 styles로 불러옵니다.
그 이유는 하나의 스타일을 담고 있는 것이 아니라 복수의 스타일을 담고 있다는 의미 때문인데요.
그렇기 때문에 style보다 styles라고 하는 게 더 옳을 수 있습니다.

@clianor
Copy link
Collaborator

clianor commented Jan 19, 2024

질문 주신 내용에 좀 더 집중하면서 답변드리는 것이 좋을 것 같아서 그 부분에 대해 답변드리겠습니다.

질문.
비밀번호 입력과 비밀번호 확인 입력을 별도로 분리하여 구현했지만, 이것이 올바른 방법인가?
이 두 가지를 하나의 공통 컴포넌트로 만들어서 유효성 검사 함수와 입력한 비밀번호를 선택적으로 받을 수 있는 방법이 있는지?

답변.
저였더라면 두 컴포넌트를 분리하지 않았을 것 같습니다.
두 컴포넌트는 생김새는 100%로 동일하고 Input과 Icon Button이 결합된 형태의 작은 단위의 컴포넌트로 보입니다.

atomic pattern에 따르면 Molecule 정도로 판단할 수 있어 보입니다.
그렇다면 PasswordInput.tsx에는 비즈니스 로직과 관련된 로직은 작성되지 않아야 합니다.

UI와 관련된 로직만이 PasswordInput 컴포넌트 내부에 있어야 하는데요.
여기서 UI 로직을 찾아보자면 비밀번호 표시 기능이라고 할 수 있습니다.
그리고 비즈니스 로직을 찾아보자면 유효성 검사 로직비밀번호 일치 여부라고 볼 수 있겠습니다.

그렇다면 비즈니스 로직의 두 기능은 어디에 위치하는 게 좋을까 생각해 보실 수 있는데요.
이러한 기능은 PasswordInput 내부에서 구현하는 것이 아니라 PasswordInput은 onChange 혹은 onBlur와 같은 이벤트로 상위 컴포넌트에서 제어할 수 있도록 열어주면 됩니다.

SignupForm 혹은 SigninForm이라는 각각의 컨테이너에서 유효성 검사비밀번호 일치 여부를 원하는 시점에 동작하도록 로직을 작성해 주시면 됩니다.

  1. onChange 이벤트를 사용한다면 값이 변경될 때
  2. onBlur 이벤트를 사용하신다면 인풋에서 포커스가 벗어났을 때
  3. onSubmit 이벤트를 사용하신다면 폼이 제출될 때

만약 onChange 이벤트를 이용해 로직을 작성하게 된다면 아래와 같이 작성해 볼 수 있겠네요.
아래 코드는 참고용으로만 작성된 코드라 input에 PasswordInput을 대입해 주시면 됩니다.

const isValidPassword = (password: string) => true;

const TestForm = () => {
  const [formState, setFormState] = React.useState({
    email: "",
    password: "",
    passwordConfirm: "",
  });

  const handleEmailChange = (event: React.ChangeEvent<HTMLInputElement>) =>
    setFormState((prev) => ({ ...prev, email: event.target.value }));
  const handlePasswordChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const {
      currentTarget: { value },
    } = event;
    if (isValidPassword(value))
      setFormState((prev) => ({ ...prev, password: value }));
  };
  const handlePasswordConfirmChange = (
    event: React.ChangeEvent<HTMLInputElement>
  ) => {
    const {
      currentTarget: { value },
    } = event;
    if (isValidPassword(value))
      setFormState((prev) => ({ ...prev, passwordConfirm: value }));
  };

  return (
    <form>
      <input
        type="email"
        value={formState.email}
        onChange={handleEmailChange}
      />
      <input type="password" onChange={handlePasswordChange} />
      <input type="password" onChange={handlePasswordChange} />
      {formState.password !== formState.passwordConfirm && (
        <p>패스워드가 일치하지 않습니다.</p>
      )}
    </form>
  );
};

@clianor
Copy link
Collaborator

clianor commented Jan 19, 2024

위의 답변처럼 코드가 작성된다면 로그인 페이지와 회원가입 페이지가 같은 인풋 컴포넌트들을 공유하게 됩니다.
페이지가 다르다고 다른 컴포넌트를 작성하게 되지 않는 점 유의해 주세요.

@clianor clianor merged commit faea025 into codeit-bootcamp-frontend:part3-이해빈 Jan 19, 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