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

[4주차 기본/공유 과제] 웨비들의 회원가입 #5

Open
wants to merge 29 commits into
base: main
Choose a base branch
from

Conversation

sinji2102
Copy link
Contributor

@sinji2102 sinji2102 commented May 10, 2024

✨ 구현 기능 명세

🧩 기본 과제

  1. 메인 페이지

    • 메인 이미지 or 비디오 넣기
    • 내정보페이지와 회원가입 페이지로 이동할 수 있는 버튼 구현
  2. 로그인 페이지

    • 아이디와 비밀번호를 입력할 수 있는 input구현
    • Login page 이미지 넣기
    • 로그인 버튼(기능)과 회원가입 페이지 이동 버튼 구현
    • 로그인 실패시 해당 에러메세지를 alert로 띄어주기
    • useParam 활용해서 id값 보유하고 있기.
  3. 회원가입 페이지

    • 아이디, 패스워드, 닉네임, 핸드폰 번호를 입력 받는 페이지 구현
    • 회원가입 버튼 클릭시 post api 통신을 진행하고 성공시 회원가입이 완료되었다는 메시지를 보여주는 alert 띄워준 후, 로그인 메인페이지로 이동
    • 아이디 중복, 비밀번호 형식 오류, 전화번호 형식 오류 등 모든 에러 alert로 메세지 보여주기
    • 비밀번호와 전화번호 형식은 input 아래에 보여주기
  4. 마이페이지

    • get 메소드를 사용해 사용자 정보를 가져오기
    • 서버에서 받아온 ID, 닉네임, 전화번호 데이터를 렌더링
    • 비밀번호 변경 토글을 사용해 비밀번호 변경 폼을 on/off할 수 있도록 구현
    • 기존 비밀번호 입력, 새로운 비밀번호 입력, 새로운 비밀번호 확인 input 구현
    • input이 비어있을 경우 api 작동되지 않도록 구현
    • 에러 발생시 api error객체 안 error message를 사용해 alert 띄우기
    • 홈 이동 버튼 구현

🔥 심화 과제

  1. 메인페이지

    • 비디오에 여러 기능을 적용
  2. 로그인 페이지

    • input이 비어있을 경우 api요청 보내지 않고 아래 error message를 띄워주기
  3. 회원가입 페이지
    input이 비어있는 상태로 api연결 시도했을시

    • 해당 input 테두리 색상 변경
    • input에 focus 맞추기
    • api요청 금지
    • 전화번호 양식 정규표현식으로 자동입력되도록 설정 (숫자만 입력해도 "-"가 붙도록)
    • 비밀번호 검증 유틸 함수 구현 (검증 통과되지 않을시 api요청 금지)

공유과제

  • prettier, eslint, styleLint에 대해
  • lighthouse에 대해

링크 첨부(팀 블로그 링크) :
prettier, eslint, styleLint에 대해


📌 내가 새로 알게 된 부분

  • 일단 PR을 날려야 하므로... 차차 추가하겠습니다... 🥺

💎 구현과정에서의 고민과정(어려웠던 부분) 공유!

  • 코드 리뷰하는 분들에게 너무너무 죄송하고... 코드가 너무 더러워서 input section 등 자주 사용되는 부분을 공통 컴포넌트로 빼고 싶었으나 시간 관계로 버튼 컴포넌트만 생성하였습니다... 🥺
  • 심화과제를 구현하지 못했는데, 전화번호 정규표현식을 시도했으나 실패했습니다... 관련한 코드는 나중에 첨부할게요!
  • prettier, ESLint 적용 과정에서 어려움이 컸는데.... 내일 건휘 오빠와 해결해보겠습니다!! 🔥

🥺 소요 시간

  • 2일

🌈 구현 결과물

구현 영상 노션

제가 카드 뒤집기 하면서 branch가 꼬였는지........ Files changed에 3주차 과제가 들어갔네요... 🥺 코드리뷰 하시는 분들 불편하실 텐데 죄송합니다!!! 😭

@sinji2102 sinji2102 requested a review from jungwoo3490 May 10, 2024 13:56
@sinji2102 sinji2102 requested review from KIMGEONHWI and ljh0608 May 10, 2024 13:56
@sinji2102 sinji2102 self-assigned this May 10, 2024
@sinji2102 sinji2102 changed the title 4주차 기본/공유 과제 [4주차 기본/공유 과제] 웨비들의 회원가입 May 10, 2024
Copy link
Member

@jungwoo3490 jungwoo3490 left a comment

Choose a reason for hiding this comment

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

지금 전체적으로 axios의 결과값을 받는 과정을 동기처리하기 위해 async await을 사용하셨더라구요!! 리뷰에 남겼듯이 axios 자체는 Promise를 반환하는 패키지이니 이 이점을 살려 then catch로 resolve reject를 처리해보는 연습을 하는 것도 좋을 것 같아요!!

또 API 요청 로직은 뷰와는 상관없는 로직이니 외부 모듈로 분리해서 import하여 호출하는 식으로 & 조금 더 심화적으로 간다면 커스텀훅으로 만드는 연습을 해보아도 좋을 것 같다는 생각입니다 :)

린트 세팅부터 힘들었을텐데 고생 많았어요!!!!! 👍🏻👍🏻🍀

Comment on lines +1 to +10
import globals from "globals";
import pluginJs from "@eslint/js";
import pluginReactConfig from "eslint-plugin-react/configs/recommended.js";


export default [
{languageOptions: { globals: globals.browser }},
pluginJs.configs.recommended,
pluginReactConfig,
];
Copy link
Member

Choose a reason for hiding this comment

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

eslint 설정할 때 이 config 파일 없이도 세팅할 수 있어요!! 이거는 합세 PR 확인해보면 좋을 것 같습니다~~!!

Comment on lines +10 to +16
<>
<GlobalStyle />
<ThemeProvider theme={theme}>
<RouterProvider router={router} />
</ThemeProvider>

</>
Copy link
Member

Choose a reason for hiding this comment

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

다음과 같이 해주면 빈 태그를 사용하지 않아도 되겠죠!!

Suggested change
<>
<GlobalStyle />
<ThemeProvider theme={theme}>
<RouterProvider router={router} />
</ThemeProvider>
</>
<ThemeProvider theme={theme}>
<GlobalStyle />
<RouterProvider router={router} />
</ThemeProvider>

Choose a reason for hiding this comment

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

다음과 같이 해주면 빈 태그를 사용하지 않아도 되겠죠!!

빈 태그를 사용하면 문제가 되는 부분이 있나요??

Comment on lines +1 to +31
import React from 'react'
import styled from "styled-components";

function BtnComponent({ buttonTitle, onClickFunc}) {
return (
<ButtonComponent type="button" onClick={onClickFunc}>
{buttonTitle}
</ButtonComponent>
);
}

export default BtnComponent

const ButtonComponent = styled.button`
display: flex;
justify-content: center;
align-items: center;

width: 6rem;
height: 2rem;
margin: 2rem;
border: 0;
border-radius: 0.7rem;


background-color: ${({ theme }) => theme.colors.LightBlue2};

&:hover{
background-color: ${({ theme }) => theme.colors.LightBlue3};
}
`
Copy link
Member

Choose a reason for hiding this comment

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

버튼이 재사용성이 높아 컴포넌트로 분리해준거 아주 좋습니다!!!

Choose a reason for hiding this comment

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

버튼 컴포넌트로 분리해주는거 너무 좋습니다!! 리팩토링 할 때 저도 꼭 분리 해야겠어요.

@@ -0,0 +1,17 @@
import { React, useEffect} from 'react';
Copy link
Member

Choose a reason for hiding this comment

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

이 import는 사용되지 않으면 제거해주기!!

Comment on lines +15 to +17
const DropdownComponent = styled.div`

`
Copy link
Member

Choose a reason for hiding this comment

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

요건 무슨 코드일까요 ?0?

const memberId = response.headers.location;
navigate(`/main/${memberId}`)
alert(response.data.message);
console.log(response.data);
Copy link
Member

Choose a reason for hiding this comment

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

console문은 개발 중간중간 지워주는 습관을 들여봅시다!!!

Comment on lines +38 to +51
<IDInputSection>
ID
<IDInput
type="text"
value={userId}
onChange={(e) => setUserId(e.target.value)} />
</IDInputSection>
<PWInputSection>
PW
<PWInput
type="text"
value={userPwd}
onChange={(e) => setUserPwd(e.target.value)} />
</PWInputSection>
Copy link
Member

Choose a reason for hiding this comment

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

요런 Section들이 로그인 페이지 말고도 자주 사용되는데 공통 컴포넌트로 분리시켜주면 좋겠네요!!!
PR에 요 부분 언급한 거 확인했고 분리의 필요성을 느꼈다는 것만으로 아주 굿입니다 👍🏻👍🏻👍🏻

margin-bottom: 3rem;
`

const IDInputSection = styled.section`
Copy link
Member

Choose a reason for hiding this comment

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

요런 빈 Styled 컴포넌트를 사용한 이유가 단순 태그 네이밍 때문일까요....? 요런 방식이 괜찮은지 아닌지에 대한 확신이 들지 않아서 조언은 드리지 못하겠지만.... 다른 분들은 어떻게 생각하는지 궁금하네요!!!

Choose a reason for hiding this comment

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

요런 빈 Styled 컴포넌트를 사용한 이유가 단순 태그 네이밍 때문일까요....? 요런 방식이 괜찮은지 아닌지에 대한 확신이 들지 않아서 조언은 드리지 못하겠지만.... 다른 분들은 어떻게 생각하는지 궁금하네요!!!

저도 궁금하네요. 신지님의 의도는 태그 네이밍 때문에 사용한것처럼 느껴지는데 맞을까요?

Comment on lines +20 to +35
const getUserData = async() => {
try {
const response = await axios.get(
`${import.meta.env.VITE_SERVER_URL}/member/info`,
{
headers: {
memberId: location
}
});
setUserData(response.data.data);
return response.data.data;
} catch (err) {
console.log(err);
alert(err.response.data.message);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

요 부분도 별도의 외부 모듈로 정의하고 호출하는 게 더 깔끔할 것 같다는 생각이 듭니다!!

Comment on lines +39 to +67
const patchPwdData = async() => {

if (!userPwd || !newPwd || !checkPwd) {
alert('모든 정보를 입력해 주세요!');
return;
}

try {
const response = await axios.patch(
`${import.meta.env.VITE_SERVER_URL}/member/password`,
{
previousPassword : userPwd,
newPassword : newPwd,
newPasswordVerification : checkPwd,
},
{
headers: {
memberId: location
}
}
);

alert(`비밀번호가 ${newPwd}로 변경되었습니다!`);
return response.data.data;
} catch (err) {
console.log(err);
alert(err.response.data.message);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

요기두요!!

Copy link

@KIMGEONHWI KIMGEONHWI left a comment

Choose a reason for hiding this comment

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

컴포넌트 분리도 하려고 노력하고 전체적으로 코드도 깔끔하게 작성되어 있는거 같아요! 저도 많이 부족한 부분이지만 정우님이 코리 남겨준것처럼 별도 외부 모듈로 호출해서 사용하는 방법을 활용하는 연습을 같이 해봐요 ㅎㅎ 4주차 과제하느라 고생 많았어요~

Comment on lines +1 to +31
import React from 'react'
import styled from "styled-components";

function BtnComponent({ buttonTitle, onClickFunc}) {
return (
<ButtonComponent type="button" onClick={onClickFunc}>
{buttonTitle}
</ButtonComponent>
);
}

export default BtnComponent

const ButtonComponent = styled.button`
display: flex;
justify-content: center;
align-items: center;

width: 6rem;
height: 2rem;
margin: 2rem;
border: 0;
border-radius: 0.7rem;


background-color: ${({ theme }) => theme.colors.LightBlue2};

&:hover{
background-color: ${({ theme }) => theme.colors.LightBlue3};
}
`

Choose a reason for hiding this comment

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

버튼 컴포넌트로 분리해주는거 너무 좋습니다!! 리팩토링 할 때 저도 꼭 분리 해야겠어요.

margin-bottom: 3rem;
`

const IDInputSection = styled.section`

Choose a reason for hiding this comment

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

요런 빈 Styled 컴포넌트를 사용한 이유가 단순 태그 네이밍 때문일까요....? 요런 방식이 괜찮은지 아닌지에 대한 확신이 들지 않아서 조언은 드리지 못하겠지만.... 다른 분들은 어떻게 생각하는지 궁금하네요!!!

저도 궁금하네요. 신지님의 의도는 태그 네이밍 때문에 사용한것처럼 느껴지는데 맞을까요?

const getUserData = async() => {
try {
const response = await axios.get(
`${import.meta.env.VITE_SERVER_URL}/member/info`,

Choose a reason for hiding this comment

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

환경변수를 사용해서 민감한 정보를 숨김으로써 보안에도 큰 도움이 된다고 하는데 신지님은 잘 사용하셨네요. 굿굿입니다.

const [userName, setUserName] = useState("");
const [userNum, setUserNum] = useState("");

let [inputNum, setInputNum] = useState("")

Choose a reason for hiding this comment

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

혹시 이부분은 회원가입 페이지에서 사용이 안되고 있는거 같은데 이유가 있을까요? 필요없으면 지워도 될거 같아요!

Choose a reason for hiding this comment

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

혹시 이부분은 회원가입 페이지에서 사용이 안되고 있는거 같은데 이유가 있을까요? 필요없으면 지워도 될거 같아요!

let [inputNum, setInputNum] = useState("")

이 부분입니다!

alert(response.data.message);
return response.data;
} catch (err) {
console.log(err);

Choose a reason for hiding this comment

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

콘솔 지워주기!

Comment on lines +10 to +16
<>
<GlobalStyle />
<ThemeProvider theme={theme}>
<RouterProvider router={router} />
</ThemeProvider>

</>

Choose a reason for hiding this comment

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

다음과 같이 해주면 빈 태그를 사용하지 않아도 되겠죠!!

빈 태그를 사용하면 문제가 되는 부분이 있나요??

Comment on lines +7 to +24
export const router = createBrowserRouter([
{
path: "/",
element: <Login />,
},
{
path: "/signup",
element: <SignUpPage />,
},
{
path: "/main/:location",
element: <MainPage />,
},
{
path: "/mypage/:location",
element: <MyPage />,
},
]);

Choose a reason for hiding this comment

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

createBrowserRouter 적용한 거 좋습니다!!! 저도 저번 코리에서 알게 된 건데 react-router에서 createBrowserRouter를 권장한다고 하네요!!

오!! 좋은 정보네요.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants