[week9] mission3 조시/정유성 - #135
Conversation
JeongCW0522
left a comment
There was a problem hiding this comment.
피드백
9주차 미션 고생 많으셨습니다! 😊
이번 주차에서는 리액트의 너무너무 중요한 부분인 전역 상태 관리에 대해서 학습해보았는데 Redux부터 요즘 많이 사용하는 Zustand와 같은 상태 관리 라이브러리를 직접 활용해보면서 왜 상태관리가 중요한지, 어떤 식으로 하는지 감을 잡으셨을 것 같습니다 ㅎㅎ
이번 주차는 크게 어렵지는 않았을 거라 생각합니다! 리뷰는 가볍게 보고 반영해주세요!
드디어 워크북도 한 주차를 남겨두고 있네요 ㅎㅎ
마지막 주차까지 조금만 더 힘내주세요!
그럼 10주차도 화이팅입니다!!! 💪
| decrease: (id: string) => void; | ||
| removeItem: (id: string) => void; | ||
| clearCart: () => void; | ||
| calculateTotals: () => void; |
There was a problem hiding this comment.
calculateTotals 타입은 인터페이스에서 제거해도 괜찮을 것 같습니다! 이미 모든 액션이 내부적으로 calcTotals를 자동 호출하고 있으니까요 ㅎㅎ
| } | ||
|
|
||
| // ── 합계 계산 유틸 ─────────────────────────────────────────── | ||
| function calcTotals(items: CartItem[]) { |
There was a problem hiding this comment.
함수는 웬만하면 화살표형 함수를 사용해주세요!
| return items.reduce( | ||
| (acc, item) => { | ||
| acc.amount += item.amount; | ||
| acc.total += Number(item.price) * item.amount; |
There was a problem hiding this comment.
price를 Number로 변환하는걸 보니 string으로 받는 것 같은데 그냥 CartItem 타입에서 number로 수정해주는 게 더 좋을 것 같습니다!
| clearCart(); | ||
| closeModal(); | ||
| }; | ||
|
|
There was a problem hiding this comment.
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"> |
There was a problem hiding this comment.
보통 외부 레이아웃을 눌렀을 때 모달이 닫히도록 해주는 것이 일반적입니다 ㅎㅎ
<div
className="fixed inset-0 z-50 flex items-center justify-center bg-black/50"
onClick={handleCancel}
>
| <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> |
There was a problem hiding this comment.
장바구니가 비어있을 때 보이는 예외처리 잘 해주셨네요!
📂 관련 이슈
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
💬 기타 설명
스토어 구조
store/useCartStore.ts— 장바구니 데이터 및 액션 관리store/useModalStore.ts— 모달 열림/닫힘 상태 관리Redux → Zustand 주요 변경점
createSlice+configureStorecreate<T>()useSelector/useDispatchuseCartStore()구조 분해<Provider store={store}>calculateTotals별도 dispatchcalcTotals()자동 호출상태 흐름
openModal()→isOpen: true→<Modal />렌더링closeModal()→isOpen: false→ 모달 사라짐clearCart()+closeModal()→ 목록 초기화 및 모달 닫힘