Skip to content

Conversation

@LeeTaegyung
Copy link
Collaborator

요구사항

기본

중고마켓

  • 중고마켓 페이지 주소는 “/items” 입니다.
  • 페이지 주소가 “/items” 일때 상단네비게이션바의 '중고마켓' 버튼의 색상은 “3692FF”입니다.
  • 상단 네비게이션 바는 이전 미션에서 구현한 랜딩 페이지와 동일한 스타일로 만들어 주세요.
  • 상품 데이터 정보는 https://panda-market-api.vercel.app/docs/#/ 에 명세된 GET 메소드 “/products” 를 사용해주세요.
  • '상품 등록하기' 버튼을 누르면 “/additem” 로 이동합니다. ( 빈 페이지 )
  • 전체 상품에서 드롭 다운으로 “최신 순” 또는 “좋아요 순”을 선택해서 정렬을 할 수 있습니다.

중고마켓 반응형

  • 베스트 상품
    • Desktop : 4개 보이기
    • Tablet : 2개 보이기
    • Mobile : 1개 보이기
  • 전체 상품
    • Desktop : 12개 보이기
    • Tablet : 6개 보이기
    • Mobile : 4개 보이기

심화

  • 페이지 네이션 기능을 구현합니다.

주요 변경사항

  • 스프린트 미션 1~4 리액트로 반영 하였습니다.

스크린샷

image
image
image

멘토에게

  • 전체 상품 영역에 있는 드랍다운 정렬 기능을 열고 닫을때마다 상태 관리를 하게 되었더니 불필요하게 AllProductArea 컴포넌트를 계속 재렌더링하고 있는거 같아서 따로 컴포넌트를 뺐습니다. 그런데 아무리 생각해봐도 공통으로 사용될것 같지도 않고, 단순히 on/off 때문에 컴포넌트 폴더 내에 생성을 하는게 맞지 않다는 생각이 들어서 AllProductArea 파일 내부에 컴포넌트를 생성하였는데 이것도 잘못된 방법 같다는 생각이 들어서요. 보통 어떻게 하는 것이 맞는지 궁금합니다!
  • useMemo와 useCallback이 올바르게 사용되었는지 궁금합니다.
  • 컴포넌트가 제대로 분리되었는지, 로직이 잘 분리되었는지, 폴더 구조도 제대로 분리해서 사용하고 있는지 봐주시면 감사하겠습니다!
  • 셀프 코드 리뷰를 통해 질문 이어가겠습니다.

hanseulhee and others added 25 commits October 10, 2023 14:15
…ithub-actions

[Fix] delete merged branch github action
@LeeTaegyung LeeTaegyung added the 매운맛🔥 뒤는 없습니다. 그냥 필터 없이 말해주세요. 책임은 제가 집니다. label May 28, 2025
@LeeTaegyung LeeTaegyung requested a review from addiescode-sj May 28, 2025 05:20
Copy link
Collaborator

@addiescode-sj addiescode-sj left a comment

Choose a reason for hiding this comment

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

수고하셨습니다!
전체적으로 잘 하셨는데,
컴포넌트를 분리하는 기준, 메모이제이션을 적용하는 기준 관련해서 리팩토링 진행해보시면 좋을것같네요 :)

주요 리뷰 포인트

  • 폴더 구조
  • 컴포넌트 분리 피드백
  • 메모이제이션 적용 피드백
  • 상태 관리 관련 피드백

Copy link
Collaborator

Choose a reason for hiding this comment

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

src 바로 밑에 있는 components 폴더는 공용 폴더로 쓰는게 일반적입니다.
AllProductArea 컴포넌트가 프로그램 내에서 여기저기 쓰이는게 아니라면 사용하는 입장에서 가까운 (찾기 편한) 위치에 두는게 좋겠죠?

src > pages > ItemsPage > components 경로안으로 파일 위치를 바꿔볼까요?

Comment on lines +47 to +53
const ITEM_COUNT = {
WEB: 10,
TABLET: 6,
MOBILE: 4,
};

const INIT_PAGE_SIZE = getItemCount(ITEM_COUNT);
Copy link
Collaborator

Choose a reason for hiding this comment

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

만약 이런 상수들도 여러 페이지에서 공유된다면 src > constants 폴더를 만들고 그 안에 위치하는 방법으로 관리하셔도 됩니다!

Comment on lines +58 to +60
const [pageSize, setPageSize] = useState(INIT_PAGE_SIZE);
const [productList, setProductList] = useState([]);
const [totalCount, setTotalCount] = useState(0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

재사용 가능한 로직이 있다면 -> 커스텀 훅으로, UI는 -> 컴포넌트로 중복을 제거해주실수있습니다. 또, 컴포넌트는 재사용 목적이 아니더라도 한 컴포넌트가 너무 많은 역할을 담당하고있을때, 컴포넌트 단위로 고유의 데이터 관리가 필요할때 등등 여러 상황에서 분리가 필요합니다.

AllProductsArea 컴포넌트는 data fetching의 결과로 전체 상품을 조회하고 렌더링하는 역할을 담당하도록 유지하는게 맞아요.
이중에 페이지네이션 로직이 해당 컴포넌트에 결합되어있으면 다른 페이지에서 페이지네이션이 필요할때마다 새로 코드를 작성해야할테니 코드 중복이 늘어나겠죠?

처음 작성할때부터 재사용 가능한 페이지네이션 로직은 커스텀훅으로 분리해보면 어떨까요? :)

<>
<h2 className={styles.bestProductArea__title}>베스트 상품</h2>
<div className={styles.bestProductArea__content}>
<ProductList list={bestList.slice(0, pageSize)} type="best" />
Copy link
Collaborator

Choose a reason for hiding this comment

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

list prop은 페이지네이션 처리된 데이터를 조합해 넘긴다기보단 초기 데이터가 넘어가는 느낌이네요! 이 용도라면 initialData가 더 명확한 네이밍인것같아요.

하지만 이 방법은 지금으로써는 복잡도만 올라가고 불필요한 처리라고 생각됩니다.
원본 배열 그대로 넘기고 ProductList 자체에서 페이지네이션 처리를 하는 방법으로 개선해보면 어떨까요?

Copy link
Collaborator

Choose a reason for hiding this comment

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

해당 파일에서 useMemo, useCallback을 사용해 메모이제이션을 적용하셨는데 불필요한 최적화라고 생각됩니다.

일반적으로 memoization이 유용한 경우는 이런 경우들입니다:

  • 자식 컴포넌트에 prop으로 전달되는 콜백 함수
  • 의존성 배열에 포함되어 다른 훅에서 사용되는 함수
  • 복잡한 로직이 포함되어 연산에 드는 비용이 비싼 함수
  • 계산 비용이 큰 값

메모이제이션을 사용하면, 필연적으로 메모이제이션 처리를 위해 추가적인 비용이 발생합니다 (메모리 공간 할당, 메모이제이션 처리 연산 등).

따라서 성급한 최적화는 피해주시는것도 좋은 개발 습관입니다.
이 경우 단순한 연산만을 수행하고있기때문에 전혀 계산 비용이 크지 않은 상황이죠? :)

Comment on lines +16 to +26
const INIT_VALUE = { email: "", password: "" };
const INIT_VALID = {
email: {
isValid: null,
msg: "",
},
password: {
isValid: null,
msg: "",
},
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

상태를 객체로 관리하게되면 값 하나만 바뀌어도 전체 객체가 새로운 참조로 변경되기때문에 불필요한 리렌더링이 발생해요. 개별적으로 state를 만들어서 관리하시는게 좋습니다 :)

Comment on lines +45 to +46
const [userValues, setUserValues] = useState(INIT_VALUE);
const [valueValids, setValueValids] = useState(INIT_VALID);
Copy link
Collaborator

Choose a reason for hiding this comment

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

여기서도 개별적으로 상태관리할수있도록 바꿔주세요! :)


// 비밀번호 확인 필드 함수 재정의
// 렌더링마다 함수 재생성 방지를 위해 useCallback 사용
const redefinePasswordConfirm = useCallback(
Copy link
Collaborator

Choose a reason for hiding this comment

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

여기서도 useCallback과 useMemo를 쓰셨는데, 성급한 최적화는 아닐지 위 코멘트 보시면서 다시 한번 생각해볼까요? :)

이메일
</label>
<div className="auth-form__input-box">
<input
Copy link
Collaborator

Choose a reason for hiding this comment

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

form과 input은 디자인시스템에도 있고 프로그램 내 여기저기서 쓰일텐데,
컴포넌트별로 코드를 중복해서 사용하는것보다 컴포넌트화해주면 좋겠죠? :)

Comment on lines +142 to +143
{!valueValids.email.isValid && (
<p className="auth-form__error-msg">{valueValids.email.msg}</p>
Copy link
Collaborator

Choose a reason for hiding this comment

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

리턴문은 항상 깔끔하게 유지하는 습관을 드려보시면 좋습니다 :)

const emailIsValid = !valueValids.email.isValid;
조건식을 상수로 정리해주면 복잡해보이는 리턴문 일부를 더 읽기 쉽고 이해하기 쉽게 바꿔줄수있겠죠? :)

@addiescode-sj addiescode-sj merged commit ff284a0 into codeit-bootcamp-frontend:React-이태경 Jun 19, 2025
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.

4 participants