-
Notifications
You must be signed in to change notification settings - Fork 10
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
[7주차] 로컬무드 미션 제출합니다. #4
base: main
Are you sure you want to change the base?
Conversation
Storybook setting
Feat:yarn-berry(zero-installs) 세팅 완료
Fix:스토리북 실행 시 esLint 오류 해결
Feat:header 레이아웃 완성
Feat:투표 메인 페이지 생성
파트장 투표 페이지 생성
Feat:데모데이 투표 카테고리 선택 페이지 생성
Chore:로그인 처리를 위해 user 정보 임의변경
Feat:유저 정보 api 연결로 Auth HOC 처리
Feat:로그아웃 로직 생성
Fix:로그인에는 로그인으로 버튼 텍스트 수정
Feat:비밀번호 input 텍스트 type password 처리
Feat:투표장 투표 클릭 시 버튼 색깔 변경
메인에 최종 병합
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.
실제 프로젝트 진행에 앞서서 거칠 프로세스들을 미리 적용해주신 부분들이 인상적이었습니다. 오늘도 많이 배워갑니다! 수고많으셨어요 😊
import type { StorybookConfig } from "@storybook/react-webpack5"; | ||
|
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.
스토리북을 사용하신 점이 흥미롭네요! 들어보기만 했는데 저도 공부해봐야겠어요 ㅎㅎ
.yarn/* | ||
!.yarn/cache | ||
!.yarn/patches | ||
!.yarn/plugins | ||
!.yarn/releases | ||
!.yarn/sdks | ||
!.yarn/versions |
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.
비효율적인 node modules의 문제점을 해결하고자 패키지 매니징 방식으로 yarn berry
를 채택한 점이 인상깊었습니다 :)
@@ -7,7 +7,7 @@ export interface VoteSelectionProps { | |||
} | |||
|
|||
export interface VoteResultProps { | |||
type: SELECT_TYPE; | |||
type: SELECT_TYPE.PartLeader | SELECT_TYPE.Demoday; |
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.
타입을 유연하게 지정을 잘 하시는 것 같습니다!
import { useMediaQuery } from "react-responsive"; | ||
|
||
export default function MediaQuery() { | ||
const isDesktop = useMediaQuery({ minWidth: 1024 }); | ||
const isTablet = useMediaQuery({ minWidth: 768, maxWidth: 1024 }); | ||
const isMobile = useMediaQuery({ maxWidth: 768 }); | ||
|
||
return { isDesktop, isTablet, isMobile }; | ||
} |
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.
mediaQuery.ts
를 style폴더에 따로 만들어주고, useMediaQuery
훅을 사용하고 MediaQuery
를 호출하여 컴포넌트 별로 현재 뷰포트에 따라 다른 뷰를 구현하신 점 배워갑니다!
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.
저도 배워갑니다. 이렇게 사용할 수 있겠군요 !
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.
반응형 구현이 깔끔하네요 👍👍
@@ -0,0 +1,15 @@ | |||
import { useMutation } from "@tanstack/react-query"; |
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.
리액트 쿼리...겨울방학에 저도 꼭 배워가고싶네요
headLine0: ` | ||
font-family: "Pretendard Variable", sans-serif; | ||
font-size: 4.8rem; | ||
font-style: normal; | ||
font-weight: 600; | ||
line-height:7rem; | ||
letter-spacing: -0.6px; | ||
`, |
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.
디자인 시스템에 따라 폰트 스타일을 이렇게 지정해주면 사용할 때 편할 거 같습니다~!
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.
바쁘실 텐데 수고하셨습니다. 많이 배워가용. 사용하신 storybook도 공부해봐야될것 같고, vite도 궁금하고, 공부할 게 많다고 느꼈습니다. 고생하셨습니다! 최고 !
import { useMediaQuery } from "react-responsive"; | ||
|
||
export default function MediaQuery() { | ||
const isDesktop = useMediaQuery({ minWidth: 1024 }); | ||
const isTablet = useMediaQuery({ minWidth: 768, maxWidth: 1024 }); | ||
const isMobile = useMediaQuery({ maxWidth: 768 }); | ||
|
||
return { isDesktop, isTablet, isMobile }; | ||
} |
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.
저도 배워갑니다. 이렇게 사용할 수 있겠군요 !
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.
과제하느라 수고하셨습니다~!! 스토리북 사용이 신기했던 것 같아요..!! 디자인은 저희랑 비슷하게 그대로 하셨네용 ㅎㅎㅎ
@@ -0,0 +1,21 @@ | |||
import type { StorybookConfig } from "@storybook/react-webpack5"; |
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.
저도 스토리북은 사용해본 적 없는데 배워갑니다~
): [Record<string, string>] { | ||
const errorMessage: Record<string, string> = {}; | ||
|
||
if ("username" in formData && !formData.username?.trim()) { |
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.
분기를 나눠서 처리해준 점 좋은 것 같습니다~!
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.
새로운 라이브러리도 배워가고 깔끔하게 작성하신 코드가 인상 깊습니다! 이번 과제도 고생하셨습니다~~
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.
스토리북은 처음 들어봐서 검색해봤는데, 다음 기회에 저도 사용해보고싶습니다 !
import { useMediaQuery } from "react-responsive"; | ||
|
||
export default function MediaQuery() { | ||
const isDesktop = useMediaQuery({ minWidth: 1024 }); | ||
const isTablet = useMediaQuery({ minWidth: 768, maxWidth: 1024 }); | ||
const isMobile = useMediaQuery({ maxWidth: 768 }); | ||
|
||
return { isDesktop, isTablet, isMobile }; | ||
} |
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.
반응형 구현이 깔끔하네요 👍👍
CRA 를 활용한 CSR 방식으로 프로젝트를 구현하였습니다.
추후 로컬무드 프로젝트에서는 Next 를 활용한 SSR 방식으로 진행할 예정이지만 해당 과제에서는 SEO 및 초기 렌더링 속도, 번들링 사이즈 등을 고려할 필요성이 적다고 생각해서 create-react-app 을 활용했습니다.
투표는 ID마다 1회로 제한되어 중복 투표가 불가합니다. 중복 투표를 시도할 시, 중복 투표가 불가하다는 창이 뜨게 됩니다.
배포 주소
localmood-vote
Vite + Yarn-berry(Zero-installs)
웹팩 번들링을 통한 개발 서버를 구동하는것이 아닌 Native ESM 방식을 사용하는 Vite를 사용하여 개발 효율성을 올렸습니다. 또한 유령 의존성, 비효율적 설치 등의 문제점을 내포하는 npm 패키지 매니지에서 벗어나 패키지 정보를 zip 파일로 관리하는 yarn-berry를 사용하였습니다. 또한 clone 이나 checkout 시 모든 의존성을 설치하는 과정에 벗어나기 위해 의존성 정보를 git에서 관리하는 zero-installs 를 도입하였습니다. file chages 가 많아 당황하실 수 있는데 비교적 작은 파일의 크기를 가진 의존성 정보를 git에서 관리하여 그렇습니다...ㅎㅎ
Storybook
사실 스토리북을 도입하기에는 규모가 작은 과제였지만, 추후 로컬무드 프로젝트에서 사용하면 그 유용성이 훨씬 커질 것이라고 판단하여 미리 도입해 보았습니다. 직접 개발 코드에 props 를 바꿔가며 컴포넌트 디자인을 테스트했던 과거와 달리 한번에 모든 컴포넌트를 파악하고 바로바로 props에 따른 컴포넌트의 변경을 파악할 수 있다는 점에서 매우 유용한 툴 인것 같습니다. 스토리북 배포까지는 해당 과제에서 진행하지는 않고 로컬 서버로만 구동시켰지만, 추후에는 배포까지 자동화 하여 프로젝트를 진행할 예정입니다.
인증 과정
회원가입을 통해 정보를 입력한 후 post 메소드를 통해 백엔드에 JSON body를 보내면 jwt를 받아왔습니다. 해당 과제에서는 refresh token의 작동 과정까지는 구현하지 않아서 Cookie를 도입하지는 않았습니다. 추후 로컬무드 과제에서는 refresh token 까지 적용할 예정으로 Cookie를 도입해보겠습니다. jwt 형식의 access token 을 받아서 interceptor를 활용해 axiosInstance 헤더에 해당 토큰을 적용하였습니다. 그 결과 token 인증 과정이 필요한 통신마다 백엔드에서는 axios 통신의 헤더를 확인한 후, 유효한 token 일 시에만 정보를 넘겨주게 됩니다. 또한 token을 localStorage에 저장하여 추후 재접속 시 다시 로그인하는 과정을 생략하였습니다. 로컬무드 프로젝트에서는 access token 기간까지 설정하여 보안에도 신경써볼 예정입니다.
media-query
react-responsive 라이브러리를 활용하여 각 파일에서 화면 크기에 따라 페이지 모습을 변경시킬 수 있도록 하였습니다.
-데스크탑
HOC Auth
로그인을 하지 않은 유저가 다른 페이지에 접속을 시도하면 로그인 창으로 navigate 시키고, 이미 로그인을 한 유저가 다시 로그인 창 및 회원가입 창에 접근하려고 할 때 메인 페이지로 navigate 시켜주는 것이 일반적인 동작이라고 판단하여 Route 해주는 파일에 HOC 처리를 해주었습니다.
Docker + AWS + Github Actions
도커파일을 작성하여 이를 build 하고 인스턴스에 이미지를 올린 뒤 컨테이너를 실행시키는 과정을 자동화 시켜 배포하였습니다.
아쉬운 점
개선해야 할 코드가 보임에도 불구하고 리팩토링을 진행할 시간이 부족하여 서로의 코드를 잘 못봐준 점이 좀 아쉬웠던 것 같습니다. 로컬무드 프로젝트 시에는 서로 단위를 나누어서 그때그때 pr 체크 후 머지를 진행함으로써 나중에 리팩토링하면 되겠지라는 마인드가 아닌 아예 리팩토링을 거의 완벽하게 하면서 가자는 마인드로 진행하기로 하였습니다.
그리고 https 가 필수요건인지 몰랐어요 ㅠㅠㅠ ㅋㅋㅋㅋㅋ 백엔드분들이 당장 https 설정 할 시간이 없을 수도 있어서 일단 말은 해놨는데 아직 바꾸진 못했습니다. 만약 백에서 가능하다고 답 오는대로 바로 https 설정 예정입니다.