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주차 기본/심화/공유 과제] API 통신 #8

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

Conversation

Minn-Choi
Copy link
Contributor

@Minn-Choi Minn-Choi commented Nov 12, 2024

✨ 구현 기능 명세

💡 기본 과제

  • React + TypeScript
  • Axios 라이브러리 사용
  • ThemeProvider, GlobalStyle 사용
  1. 로그인
  • 로그인 타이틀
  • 아이디(이름) 입력 Input
  • 비밀번호 입력 Input
  • 로그인 버튼 (hover시 배경색 바꾸기 (transition 적용))
  • 회원가입 버튼 (회원가입 페이지로 이동)
  1. 회원가입
  • 이름 - 비밀번호 - 취미 입력이 한 페이지에서 일어남 (컴포넌트만 갈아끼우기)
  • 상단에 회원가입 타이틀
  • 하단에는 로그인 페이지로 가는 링크
  1. 회원가입(이름)
  • 이름 입력 Input
  • 다음 버튼 (비밀번호 입력 폼 나옴)
  • Input 비어있을 때 버튼 비활성화
  1. 회원가입(비밀번호)
  • 비밀번호 입력 Input
  • 비밀번호 확인 Input
  • 둘 중 하나라도 비어있으면 버튼 비활성화
  • 두 비밀번호가 다르면 버튼 비활성화
  • 다음 버튼 (취미 입력 폼 나옴)
  1. 회원가입(취미)
  • 취미 입력 Input
  • 회원가입 버튼
  • Input 비어있을 때 버튼 비활성화
  • 회원가입 실패 시 에러메시지 alert 출력
  • 회원가입 성공 시 회원번호 alert 출력하고, login 페이지로 이동
  1. 마이페이지
  • 헤더에 취미, 내 정보 메뉴 탭
  • 헤더에 로그아웃 버튼
  • 로그아웃 버튼 클릭 시 token 저장 정보 삭제하고 로그인 페이지로 이동 (token 저장 위치는 자율)
  • 헤더 취미, 내 정보 취미 페이지, 내 정보 페이지 출력 (1개의 페이지로 구현해도 되고, url 달라도 됨)
  1. 마이페이지(취미)
  • 나의 취미 출력
  • 사용자 번호 입력 Input
  • 검색 버튼
  • 검색 오류시 alert
  • 검색된 취미 출력
  1. 마이페이지(내 정보)
  • 비밀번호만 입력하면 비밀번호만 변경
  • 취미만 입력하면 취미만 변경
  • 둘 다 입력하면 둘다 변경
  • 둘 다 비어있으면 alert

🔥 심화 과제

  • any 사용하지 않기
  1. 회원가입 (이름)
  • 8글자 넘어가도 버튼 비활성화 처리
  • 8글자 넘어가는 것에 대해 에러메시지 출력
  1. 회원가입 (비밀번호)
  • 비밀번호 보이기 버튼 추가
  • 8글자 넘어가도 버튼 비활성화 처리
  • 8글자 넘어가는 것에 대해 에러메시지 출력
  • 비밀번호 불일치 에러 메시지 출력
  • (선택) 에러메시지 한개만 출력해도 됨 (우선순위는 알아서)
  1. 회원가입 (취미)
  • 8글자 넘어가도 버튼 비활성화 처리
  • 8글자 넘어가는 것에 대해 에러메시지 출력

공유과제

제목: TypeScript의 .d.ts 파일 🧐

링크 첨부 : https://wave-web.tistory.com/123


❗️ 내가 새로 알게 된 점

  • TypeScript로 코드를 작성해본 것은 처음이라서 헷갈리는 부분도 있었지만 열심히 찾아봤습니다 ..!
  • 받아오는 함수나 변수 등에 타입을 지정하는 것이 익숙치 않아서 에러가 뜨기도 했지만 추후에 타입 오류 등의 여러 실수들을 잡아낼 수 있기에 좋은 것 같다고 생각했습니다 !
  • theme파일 만드는 것도 처음이었는데 협업 할때나 재사용되는 색상,폰트 들이 많을 때 정말 유용할 것 같다고 생각했습니다 !!

❓ 구현 과정에서의 어려웠던/고민했던 부분

  • 내 취미를 불러오는 과정에서 계속 그 전에 로그인했던 사용자의 취미가 뜨고, 새로고침을 하면 또 지금 로그인한 사용자의 취미가 제대로 불러와져서 무엇이 문제일까 고민해봤습니다ㅠ
    useEffect(() => { const storedToken = localStorage.getItem("token"); setToken(storedToken); }, []);
    useEffect(() => { if (token) getMyHobby(); }, [token]);
    해당 코드를 추가해서 새로고침 없이도 지금 로그인한 사용자의 취미가 불러와지는 것을 확인했습니다!

🥲 소요 시간

  • 19h

🖼️ 구현 결과물

week4.1.mp4
week4.2.mp4
week4.3.mp4

@Minn-Choi Minn-Choi linked an issue Nov 12, 2024 that may be closed by this pull request
3 tasks
@Minn-Choi Minn-Choi added ❤️최민 최민 🌳과제 과제입니다 💫Feature 새로운 기능 구현입니다 🐻Design 디자인 추가입니다 labels Nov 12, 2024
Copy link
Member

@gudusol gudusol left a comment

Choose a reason for hiding this comment

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

고생 많으셨어요
코드를 전반적으로 되게 깔끔하게 짜신 것 같습니다! 대체로 일관성도 있구요! 👍

Comment on lines +13 to +19
<Router>
<Routes>
<Route path="/" element={<Login />} />
<Route path="/signin" element={<SignIn />} />
<Route path="/mypage" element={<MyPage />} />
</Routes>
</Router>
Copy link
Member

Choose a reason for hiding this comment

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

<BrowserRouter>를 사용해서 라우팅을 구현해주셨네요!
그런데, 이 방식 대신 createBrowserRouter를 사용하는 것을 더 추천드리고 싶어요!

결론부터 말씀드리면, createBrowserRouter는 라우트 설정을 보다 명시적이고 구조적으로 작성할 수 있도록 도와주는 최신 API입니다.
또한, 코드가 더 직관적이고 관리하기 쉬워지는 장점이 있어요.

문제점

  1. 라우트 설정의 명시성 부족
    <BrowserRouter> 방식은 라우트와 컴포넌트들을 JSX 안에서 설정해야 하기 때문에, 라우트 구조가 복잡해질수록 관리가 어려워질 수 있습니다.

  2. 코드의 확장성과 유지보수
    createBrowserRouter는 라우트를 객체 형태로 정의하여 별도 파일로 분리하거나 재사용하기 쉬운 구조를 제공합니다. 이런 방식은 코드 확장성과 유지보수에 유리합니다.

따라서, createBrowserRouter를 활용하면 아래와 같은 방식으로 작성할 수 있어요:

import { createBrowserRouter, RouterProvider } from 'react-router-dom';

const router = createBrowserRouter([
  {
    path: '/',
    element: <Home />,
    children: [
      { path: 'about', element: <About /> },
      { path: 'contact', element: <Contact /> },
    ],
  },
]);

<RouterProvider router={router} />;

위와 같은 방식은 라우트 구성과 UI 구성이 분리되기 때문에 코드의 가독성과 확장성이 더 좋아집니다!

관련 공식 문서 한 번 읽어보시는 것도 추천드려요 😊

Comment on lines +5 to +7
<>
<LoginInput/>
</>
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
<>
<LoginInput/>
</>
<LoginInput/>

요렇게만 해주셔도 될 것 같아요!

Comment on lines +73 to +75
&:hover {
background-color: #D1A1E0;
}
Copy link
Member

Choose a reason for hiding this comment

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

themeProvider를 이용해서 프로젝트에서 사용하는 color값들을 지정해놨기 때문에, theme에서 가져다 쓰는것이 좋습니다.

그래야 나중에 유지보수도 쉽고, 일관성이나 가독성 측면에서도 더 좋습니다!

Comment on lines +53 to +55
<Link to="/signin" css={{ width: '100%' }}>
<button css={signInBtn}>회원가입</button>
</Link>
Copy link
Member

Choose a reason for hiding this comment

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

여기도 inline-style도 스타일링 하기보다는 다른 곳처럼 일관성있게 css객체 따로 선언해서 넣어주면 더 좋을 것 같아요~

Comment on lines +26 to +36
const response = await fetch("http://211.188.53.75:8080/user", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username: userData.username,
password: userData.password,
hobby: userData.hobby,
}),
});
Copy link
Member

Choose a reason for hiding this comment

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

요기는 왜 axios가 아니라 fetch함수를 사용하셨나요?

다른 부분을 보니 axios를 사용하셨던데, 일관성있게 요기도 axios로 통일해주는 것이 더 좋아보여요!
axios가 이런저런 기능을 많이 제공해주기도하고, 쓰기도 더 간단하구요!

Comment on lines +21 to +23
const response = await axios.get("http://211.188.53.75:8080/user/my-hobby", {
headers: {
token: token,
Copy link
Member

Choose a reason for hiding this comment

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

api를 호출할 때마다, baseUrl을 입력하고, headers를 set해주는것이 중복이 많으니 axios의 instance를 사용해보는 것도 좋은 방법일 것 같습니다!

};

useEffect(() => {
if (token) getMyHobby();
Copy link
Member

Choose a reason for hiding this comment

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

getMyHobby 함수내에서도 token 유무를 확인하고 있어서, 둘 중 한군데에서만 체크해도 괜찮을 것 같습니다

Comment on lines +20 to +21
export const myMent = css`
`;
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 +57 to +69
export const myhobby = css`
font-family: "NanumB";
color: blueviolet;
`;
export const myhobbycontent = css`
font-family: "NanumR";
color: purple;
margin-bottom: 2rem;
`;
export const other = css`
font-family: "NanumB";
color: blueviolet;
`;
Copy link
Member

Choose a reason for hiding this comment

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

myhobby와 other이 아예 똑같은 코드인데, css객체의 재사용을 고려해보는 것도 좋을 것 같습니다!

import MyProfile from "../../components/mypage/myprofile";

const MyPage = () => {
const [currentTab, setCurrentTab] = useState("hobby");
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
const [currentTab, setCurrentTab] = useState("hobby");
const [currentTab, setCurrentTab] = useState<"hobby" | "profile">("hobby");

와 같은 방식으로 특정 문자열만 올 수 있는 state의 경우 타입을 조금 더 구체적으로 지정해주면 더 안전한 코드를 작성할 수 있을 것 같아요!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
❤️최민 최민 🌳과제 과제입니다 🐻Design 디자인 추가입니다 💫Feature 새로운 기능 구현입니다
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature] - 4주차 API 통신
2 participants