Tech/ReactJS

결제 후 장바구니 속 아이템이 삭제되었다가 재생성되는 이슈

닝닝깅 2024. 4. 29. 11:52

📍 문제상황

장바구니 아이템을 선택한 후 결제까지 완료하면 선택했던 아이템들은 장바구니에서 삭제가 되는 것이 정상 동작이다. 그런데 내 프로젝트에서는 아이템들이 삭제되었다가 장바구니를 다시 열면 재생성되어있는 이슈가 발생했다.

삭제된 아이템이 개수가 0인 상태로 재생성되어 있었던 것.. 뭐야 무서워..

 

📍 원인 분석

콘솔을 통해 이전 장바구니 스토어 아이템 id에 해당하는 상품 데이터(=products)가 남아있는 것이 문제인 것을 찾아냈다.

결제 이후 로직은 대충 다음과 같다.

1) 결제 성공

2) zustand 장바구니 스토어 아이템 삭제

3) 장바구니 스토어 아이템 id에 해당하는 상품 데이터(=products) fetch 쿼리 캐싱 무효화

 

지난 products가 렌더링되는 근본적인 이유는 캐싱 무효화가 동작하지 않는 것이라고 생각했고, 디버깅을 시도했지만 큰 개선점을 얻지 못했다.

 

다른 방법을 찾기 위해 지난 products 렌더링됐을 때 장바구니 아이템 재생성을 유발하는 이유를 찾아보았다.

아이템 수량 변경 훅에서 그 이유를 찾을 수 있었다. 해당 훅은 아래와 같은 props를 받는다.

interface IUseQuantitySelection {
  maxQuantity: number; // 선택 가능한 최대 수량
  initialCnt?: number; // 수량 초기값 --> 초기값 없으면 0으로
  cartItemId?: string; // 장바구니 아이템일 경우 장바구니 아이템 id
}

 

이때 훅의 내부로직에서 useEffect 콜백함수에 따라 장바구니 아이템일 경우 장바구니에 해당 아이템을 장바구니 스토어에 추가시킨다. 이 과정에서 장바구니 스토어에 재생성된다.

 

  useEffect(() => {
    if (cartItemId) {
      addCartItem(cartItemId, selectedQuantity);
    }
  }, [selectedQuantity]);

수량이 변경될 때 장바구니 스토어 업데이트를 위해 추가한 로직인데 사이드이펙트가 발생한 것이다.

📍 문제 해결

초기값이 존재하는 경우(수량이 최소 1인 경우)에만 장바구니에 추가되도록 로직을 수정하였고, 정상 동작함을 확인하였다.

  useEffect(() => {
    if (cartItemId && initialCnt) {
      addCartItem(cartItemId, selectedQuantity);
    }
  }, [selectedQuantity]);

문제의 근본적인 해결은 하지 못한 것 같아 아쉬웠지만, 해결과정에서 다양한 시도를 하며 얻은 인사이트가 많기 때문에 얻은 바가 크다. 근본적 해결법은 더 고민해보는 걸로!

 

이번 프로젝트에서 뷰와 비즈니스 로직을 분리하기 위해 커스텀 훅을 적극적으로 활용했었는데, 그렇다보니 로직 설계에서 로직끼리의 상호작용을 고려하지 못한 부분이 많은 것 같다.