Skip to content

Feature/my solution 1 ~ 2#13

Open
yu-ratel wants to merge 27 commits intohacks-team:mainfrom
yu-ratel:feature/my-solution
Open

Feature/my solution 1 ~ 2#13
yu-ratel wants to merge 27 commits intohacks-team:mainfrom
yu-ratel:feature/my-solution

Conversation

@yu-ratel
Copy link
Copy Markdown

@yu-ratel yu-ratel commented Dec 8, 2025

📝 변경 사항 요약

1 ~ 2차 과제가 포함되어 있으며 공통된 변경사항을 제외한 2차 기준 변경사항을 작성하였습니다.

작업 진행 현황

  • '사용할 통화'에 따른 금액 변경
  • 상품목록 카테고리 고려 노출
  • 장바구니 기능 구현
  • error 및 loading 상태 처리

공통

Client - UI 렌더링과 직접적으로 관련된 로컬/전역 UI 상태는 React Context를 통해 관리합니다.
Server - 데이터 패칭 및 서버 상태 관리는 React Query를 통해 관리합니다.


AsyncBoundary

서버 패칭 중 발생하는 error 및 loading 상태 처리에 대해서 ui-lib 컴포넌트를 만들어 프로젝트 전체적으로 공통 패턴을 적용하였습니다.
패턴을 적용한 이유는 크게 3가지 입니다.

  1. 리액트 쿼리를 사용하면서 내부 상태인 isLoading, isError 등을 사용
  2. errorSection 및 sectionSkeletonSection 를 공통적으로 감싸는 ui 를 중복없이 사용
  3. 외부 개입없이 해당 컴포넌트안에서 로딩상태와 에러상태에 대한 솔루션을 가지고 있도록
export function AsyncBoundary({ isLoading, isError, onRetry, loadingFallback, errorFallback, children }: Props) {
  if (isLoading) {
    return loadingFallback;
  }

  if (isError) {
    return errorFallback ?? <ErrorSection onRetry={onRetry} />;
  }

  return children;
}

// 사용처 

 <AsyncBoundary
          isLoading={isLoading}
          isError={isError}
          loadingFallback={<RecentPurchaseSectionSkeleton />}
          errorFallback={
            <ErrorSection
              onRetry={() => {
                recentProducts.refetch();
                exchangeRate.refetch();
              }}
            />
          }
        >
{ ... 성공로직 } 
</AsyncBoundary>

Discriminated Union

처음엔 default type 으로 상품 추가옵션과 관련된 로직을 옵셔널로 한번에 걸어두고 아래와 같이 사용하려고 했으나

function ProductListFreeTag({ category, isOption }: { category: ProductCategory; isOption: boolean }) {
  if (category === 'CRACKER' && isOption) {
    return <ProductItem.FreeTag type="gluten" />;
  }
  if (category === 'TEA' && isOption) {
    return <ProductItem.FreeTag type="caffeine" />;
  }
  return null;
}

<ProductListFreeTag category={product.category} isOption={product.isGlutenFree ?? false} />
<ProductListFreeTag category={product.category} isOption={product.isCaffeineFree ?? false} />

해당 구조는 어떤 타입이 추가되건 ( ex. 티에서 만약 isGlutenFree를 넘겨받은 상황 ) Ts 에서 에러를 잡지못한다는 생각이 들었고
일전에 말씀해주신 구별된 유니온을 이용해 카테고리별 허용 속성이 자동 검증되어, 타입 안정성을 향상 시켰습니다.

// type 

interface ProductBase {
  id: number;
  name: string;
  category: ProductCategory;
  stock: number;
  price: number;
  description: string;
  detailDescription: string;
  images: string[];
  rating: number;
}

export type Product =
  | (ProductBase & { category: 'CHEESE' })
  | (ProductBase & { category: 'CRACKER'; isGlutenFree?: boolean })
  | (ProductBase & { category: 'TEA'; isCaffeineFree?: boolean });


// 사용처
function ProductItemFreeTag({ product }: { product: Product }) {

  switch ( product.category) {
    case 'CHEESE':
      return null;
    case 'CRACKER':
      return product.isGlutenFree && <ProductItem.FreeTag type="gluten" />;
    case 'TEA':
      return product.isCaffeineFree && <ProductItem.FreeTag type="caffeine" />;
    default:
      category satisfies never;
  }
}

🤝 리뷰어에게

1차 시기에 말씀해주신 서스펜스와 쿼리즈를 이용해서 하는 방식이 다양한 장점 ( 데이터 병렬처리 ... )이 있다고 생각하여 바꿔 보려고 했으나
기존에 작성중이던 AsyncBoundary 에 대한 의견을 듣고싶어서 변경하지 않았습니다! 이 부분에 대해서 어떻게 생각하시는지 궁금합니다.
그리고 구별된 유니온을 처음 써봐서 더 좋은 방식이 있을지 의견 나눠보고 싶습니다!

전체 서비스 내 통화 상태관리 적용
api, type, services, index.ts 로 구조 통일 (api 로직 캡슐화)
usequery 결과값 상태 이용 skeleton, errorSection 적용
옵셔널 방지를 위한 initialData 적용
usequery 결과값 상태 이용 skeleton, errorSection 적용
옵셔널 방지를 위한 initialData 적용
DiscriminatedUnion type 정의
기존 최근 구매상품 productType 네이밍 recent 추가
context 상태를 이용한 장바구니 관리 hooks 구현 ( add,remove, read, more and lessThan )
상품목록 page, 헤더 장바구니 hooks 기능 적용
usequery 결과값 상태 이용 skeleton, errorSection 적용
1. 사용할 통화에 따라 금액을 변경해주세요.
2. 선택한 상품의 상세 정보를 서버에서 불러와주세요.
3. 상품에 맞는 카테고리를 노출해 주세요.
부모 -> 자식 컴포넌트로 데이터 관리 변경
5. 장바구니에 같은 상품이 없을 경우 원하는 수량을 선택 후 장바구니에 담을 수 있어요.
5.1, 5.2, 5.3 하위 요구사항 적용
4. 상품의 상황에 따라 장바구니 버튼에 아래 내용을 출력해주세요 [4.1, 4.2, 4.3]
6. 장바구니에 같은 상품이 있을 경우 '장바구니에서 제거 버튼 클릭 시' 해당상품을 장바구니에서 삭제해 주세요.
7. 상품에 맞는 추천 제품을 노출해주세요. [7.1, 7.2]
8. 서버에 문제가 있을경우 에러화면을 노출해주세요.
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.

1 participant