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

[김민희] sprint5 #81

Merged

Conversation

smnhree
Copy link
Collaborator

@smnhree smnhree commented Jan 10, 2025

배포 링크

https://panda-market-mhkim-react.netlify.app/

요구사항

기본

공통

  • React를 사용해 진행합니다.

중고마켓 페이지

  • PC, Tablet, Mobile 디자인에 해당하는 중고마켓 페이지를 만들어 주세요.
  • 중고마켓 페이지 url path는 별도로 설정하지 않고, '/'에 보이도록 합니다.
  • 상단 네비게이션 바, 푸터는 랜딩 페이지와 동일한 스타일과 규칙으로 만들어주세요.
  • 상품 데이터는 https://panda-market-api.vercel.app/docs/에 명세된 GET 메소드 "/products" 를 활용해주세요.
  • 상품 목록 페이지네이션 기능을 구현합니다.
  • 드롭 다운으로 "최신 순" 또는 "좋아요 순"을 선택해서 정렬을 구현하세요.
  • 상품 목록 검색 기능을 구현합니다.
  • 베스트 상품 데이터는 https://panda-market-api.vercel.app/docs/에 명세된 GET 메소드 "/products"의 정렬 기준 favorite을 사용해주세요.

심화

공통

  • 커스텀 hook을 만들어 필요한 곳에 활용해 보세요.

중고마켓 페이지

  • 반응형에 따른 페이지 네이션 기능을 구현합니다.
  • 반응형으로 보여지는 물품들의 개수를 다르게 설정할때 서버에 보내는 pageSize값을 적절하게 설정합니다.

스크린샷

screenshot_sprint 5

멘토에게

  • 요소들의 재사용성을 높이기 위해 컴포넌트로 만들었는데, 부모 요소에서의 상태에 따라 컴포넌트의 스타일이나 로직을 바꿔야하는 상황이 생깁니다. prop을 받는 식으로 조정을 할 순 있겠지만, 가끔 발생하는 특수한 경우에 대한 조정이라던가 컴포넌트의 핵심적인 부분이 아닌걸 prop을 받는게 좀 어색해서 이럴 땐 어떻게 해야 하는지 고민이 있습니다. 예를 들면 이번 프로젝트에서 input, button, productCard를 컴포넌트로 분리했지만 상황에 따라 크기를 다르게 하기 위해 width를 prop으로 받는 식으로 설계했는데 이런 방식이 괜찮은지 궁금합니다.
  • productsList부분에서 코드가 너무 정신없고 많은 느낌이 있습니다. 어떤 식으로 코드를 정리하고 분리하면 좋을지 궁금합니다.
  • productsList에서 검색할 때 화면 움직임이 자연스럽지 않은데, 어떻게 개선할 수 있을지 궁금합니다.
  • 반응형 웹을 구현하기 위해 useScreenType 훅을 만들었습니다. 처음에는 useScreenType을 MarketplacePage에서 상태를 만들고(?) 자식 요소들에 prop으로 넘기는 식으로 하려고 했는데 이 screenType 상태를 어디서 관리하고 이용하는게 좋을지 궁금합니다. 사실 처음에는 모든 컴포넌트를 prop으로 screenType을 받아버리는 형태로 구현할까 생각도 했습니다... 왜냐면 대부분의 컴포넌트가 이 screenType에 따라 형태가 달라지는 것 같아서요. 근데 이건 아닌거 같아서 생각을 접었습니다...ㅎㅎ 어쨌든 이 screenType을 여러 요소들에게 어떻게 영향을 주어야 할지 고민이 되었습니다.
  • 폴더 구조에 대해서도 의견이 궁금합니다!
  • 시간이 부족해서 추가로 보완해야 할 것들이 주석으로 작성되어 있습니다.(todo:~~) 추후에 시간될 때 반영할 예정인데, 혹시 제가 작성한 부분에서 다른 의견이 있으시다면 알려주시면 많은 도움이 될 것 같습니다!

@smnhree smnhree requested a review from rjc1704 January 10, 2025 13:14
@smnhree smnhree self-assigned this Jan 10, 2025
@smnhree smnhree changed the title [김민희] Sprint5 [김민희] sprint5 Jan 10, 2025
};

const [screenType, setScreenType] = useState(
getScreenType(window.innerWidth)
Copy link
Collaborator

Choose a reason for hiding this comment

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

useState(getScreenType(window.innerWidth)) 보다는 useState(() => getScreenType(window.innerWidth)) 로 변경하시는 것이 좋겠습니다. 전자는 리렌더링이 발생할 때 마다 getScreenType 함수가 실행되지만 후자는 첫 마운트 시에만 getScreenType이 실행됩니다.

import { FooterSection } from "../../components/FooterSection/FooterSection";
import "./MarketplacePage.css";

export function MarketplacePage() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

컴포넌트를 export 할 때는 export default 를 사용하는 것을 권장 드립니다. 그냥 export(named export)는 보통 하나의 파일에서 여러개의 export 가 있을 때 사용하는 의도가 있고 하나의 컴포넌트 파일에서는 컴포넌트만 내보내는 것이 유지보수상 간결하게 인지하기 쉽습니다.

clearTimeout(timeout);
timeout = setTimeout(() => func(...args), delay);
};
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

debounce 함수의 경우, useCallback 을 이용해서 리렌더링되어도 메모리를 그대로 유지할 수 있어야 합니다. 그래야 동일한 timeout id로 clearTimeout 을 실행시켜서, 사용자가 타이핑하는 동안에는 setTimeout 에 해당하는 51번 코드가 실행되지 않도록 취소시킬 수가 있습니다. 마찬가지로 debouncedLoadProduct 함수도 useCallback 사용해서 적용해보세요. 지금은 디바운싱이 아니라 타이핑하는 한글자한글자 마다 setTimeout 코드가 실행되고 있습니다.

@rjc1704
Copy link
Collaborator

rjc1704 commented Jan 13, 2025

반응형 요구사항을 잘 만족시켜주셨습니다. 페이지네이션의 경우 UI는 잘 나타내셨지만, 페이지버튼 클릭 시 서버요청과 리렌더링이 발생해야 하는데 이 부분은 동작하지 않으니 다시 한번 확인해보시면 좋겠습니다. 질문 주신 부분에 대해 아래에 통합 답변과 일부 코드에 코멘트를 적어드렸으니 확인해보시고 가능한 부분은 스스로 리팩터링 도전해 보시면 좋겠습니다. 고생하셨습니다.

import { MarketplacePage } from "./pages/MarketplacePage/MarketplacePage"; 코드에서 바로 에러가 발생합니다. 개발모드에서는 소문자, 대문자가 틀려도 경로를 제대로 인식하는 경우가 있지만, 추후에 배포하거나 다른 누군가가 깃헙 클론받아서 실행했을 때는 경로를 찾지못하는 경우가 발생합니다.

src/pages 폴더에는 말그대로 페이지 컴포넌트만 관리하는 것을 권장 드립니다. ProductList.jsx 는 페이지 컴포넌트가 아니므로 src/components/ 안에서 관리하는 것이 좋겠습니다.
css 파일을 js/jsx 와 같은 경로에 보관하셨는데 이 같은 경우 css 파일보다는 module.css 확장자를 사용하셔서 불필요하게 셀렉터명이 중복되는 문제를 방지할 수 있습니다. 하지만 이 경우, 중복되는 css 스타일코드 역시 많아지니 각각의 jsx파일마다 css 파일을 관리하기보다는 소규모 프로젝트는 단순하게 index.css 파일하나만으로도 충분히 커버가 가능합니다. 중대형 규모로 갈 경우, 공용 css 파일(index, variables, utility), 페이지별, 컴포넌트별 css 파일을 분리하여 유지보수성을 높여서 관리하는 경우가 많습니다.

가끔 발생하는 특수한 경우에 대한 조정의 경우 props 로 받고 기본값 설정만 해두시면 충분히 유연하게 재사용성 좋은 컴포넌트로 관리하실 수 있습니다. 물론 UI 스타일상 크게 상이한 경우는 재사용성만을 위해 알아보기 힘들게 관리하기보다는 별도의 컴포넌트로 분리하는 것 또한 의미있는 컴포넌트 분리라 할 수 있습니다.

useScreenType 이라는 커스텀훅의 용도는 현재 화면크기가 모바일, 태블릿, 데스크탑인지에 따라 api 요청 시 한 페이지에 몇개씩 데이터를 가져올 것인지 pageSize 쿼리값을 분기처리하기 위한 용도로 사용되는 것이 과제 의도입니다. 모바일, 태블릿, 데스크탑 사이즈에 따라 몇 열로 리스트를 나타낼 지에 대한 레이아웃 처리는 useScreenType 에 의존하는 것이 아니라 미디어쿼리를 사용하는 것이 성능상 이점이 있습니다. html, css만으로 해결이 가능한 문제는 js를 사용하지 않는 것이 더 좋은 성능을 냅니다.

@rjc1704 rjc1704 merged commit 2a30a75 into codeit-sprint-fullstack:react-김민희 Jan 13, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants