Skip to content

[week9] mission3 조시/정유성 - #135

Open
joshuasa0122 wants to merge 7 commits into
mainfrom
josh-week9/mission3
Open

[week9] mission3 조시/정유성#135
joshuasa0122 wants to merge 7 commits into
mainfrom
josh-week9/mission3

Conversation

@joshuasa0122

@joshuasa0122 joshuasa0122 commented May 26, 2026

Copy link
Copy Markdown
Contributor

📂 관련 이슈

closes #132

🛠️ 작업 사항

  • features/cart/cartSlice.ts, features/modal/modalSlice.ts, store/store.ts 제거 — Redux 흔적 완전 삭제
  • store/useCartStore.ts 제작 — CartStore 타입 정의 및 create<CartStore>() 로 Zustand 스토어 구성
  • store/useModalStore.ts 제작 — ModalStore 타입 정의 및 isOpen 초기 상태, openModal() / closeModal() 액션 구현
  • increase / decrease / removeItem / clearCart / calculateTotals 액션 로직을 set((state) => {...}) 형태로 변환
  • decrease 로직 유지 — 수량 1 미만 시 자동 제거
  • 합계 재계산 로직을 calcTotals() 유틸로 분리 — 각 액션마다 자동 호출
  • CartPage, CartItem, Modal 컴포넌트에서 useSelector / useDispatch 제거
  • 각 컴포넌트에서 useCartStore() / useModalStore() 구조 분해 할당으로 상태·액션 연결
  • main.tsx에서 Redux <Provider> 제거
  • Modal 컴포넌트 — "네" 클릭 시 clearCart() + closeModal() Zustand 액션 연동

📸 관련 이미지 (스크린샷 또는 동영상)

2026-05-26.12.47.22.mov

💬 기타 설명

💡 Redux Toolkit으로 관리하던 전역 상태를 Zustand로 완전히 전환했습니다.

스토어 구조

  • store/useCartStore.ts — 장바구니 데이터 및 액션 관리
  • store/useModalStore.ts — 모달 열림/닫힘 상태 관리

Redux → Zustand 주요 변경점

Redux Toolkit Zustand
createSlice + configureStore create<T>()
useSelector / useDispatch useCartStore() 구조 분해
<Provider store={store}> Provider 불필요
calculateTotals 별도 dispatch 각 액션 내부에서 calcTotals() 자동 호출

상태 흐름

  • 전체 삭제 버튼 클릭 → openModal()isOpen: true<Modal /> 렌더링
  • "아니요" 클릭 → closeModal()isOpen: false → 모달 사라짐
  • "네" 클릭 → clearCart() + closeModal() → 목록 초기화 및 모달 닫힘

@joshuasa0122 joshuasa0122 self-assigned this May 26, 2026
@joshuasa0122
joshuasa0122 requested a review from JeongCW0522 May 26, 2026 03:49

@JeongCW0522 JeongCW0522 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

피드백

9주차 미션 고생 많으셨습니다! 😊
이번 주차에서는 리액트의 너무너무 중요한 부분인 전역 상태 관리에 대해서 학습해보았는데 Redux부터 요즘 많이 사용하는 Zustand와 같은 상태 관리 라이브러리를 직접 활용해보면서 왜 상태관리가 중요한지, 어떤 식으로 하는지 감을 잡으셨을 것 같습니다 ㅎㅎ

이번 주차는 크게 어렵지는 않았을 거라 생각합니다! 리뷰는 가볍게 보고 반영해주세요!

드디어 워크북도 한 주차를 남겨두고 있네요 ㅎㅎ
마지막 주차까지 조금만 더 힘내주세요!

그럼 10주차도 화이팅입니다!!! 💪

decrease: (id: string) => void;
removeItem: (id: string) => void;
clearCart: () => void;
calculateTotals: () => void;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

calculateTotals 타입은 인터페이스에서 제거해도 괜찮을 것 같습니다! 이미 모든 액션이 내부적으로 calcTotals를 자동 호출하고 있으니까요 ㅎㅎ

}

// ── 합계 계산 유틸 ───────────────────────────────────────────
function calcTotals(items: CartItem[]) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

함수는 웬만하면 화살표형 함수를 사용해주세요!

return items.reduce(
(acc, item) => {
acc.amount += item.amount;
acc.total += Number(item.price) * item.amount;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

price를 Number로 변환하는걸 보니 string으로 받는 것 같은데 그냥 CartItem 타입에서 number로 수정해주는 게 더 좋을 것 같습니다!

clearCart();
closeModal();
};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

esc로 모달을 닫는 기능도 추가해주세요!

  useEffect(() => {
    const handleKeyDown = (e: KeyboardEvent) => {
      if (e.key === "Escape") closeModal();
    };

    document.addEventListener("keydown", handleKeyDown);
    return () => document.removeEventListener("keydown", handleKeyDown);
  }, [closeModal]);


return (
// 어두운 반투명 오버레이
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

보통 외부 레이아웃을 눌렀을 때 모달이 닫히도록 해주는 것이 일반적입니다 ㅎㅎ

 <div
      className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
      onClick={handleCancel}
    >

Comment on lines +32 to +36
<div className="flex flex-col items-center justify-center py-32 gap-4 text-gray-400">
<span className="text-6xl">🎼</span>
<p className="text-lg font-semibold">장바구니가 비어있어요</p>
<p className="text-sm">음반을 추가해보세요!</p>
</div>

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

장바구니가 비어있을 때 보이는 예외처리 잘 해주셨네요!

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.

[Feat] 9주차 미션_조시

2 participants