Web

Redux Toolkit으로 Play List 장바구니 생성

sungjae0309 2026. 5. 29. 14:37

이번엔 Redux Toolkit, TypeScript, Tailwind CSS를 활용해서 전역 상태로 관리되는 플레이리스트 장바구니 화면을 구현했다.

 

이번 실습의 목표는 아래와 같았다.

  1. 음반 Mock Data 분리
  2. Redux Store 생성
  3. cartSlice 설계
  4. 수량 증가, 감소, 삭제, 전체 삭제 기능 구현
  5. 총 수량과 총 금액 자동 계산
  6. React 컴포넌트와 Redux 상태 연결
  7. Tailwind CSS로 UI 구성

1. 음반 Mock Data 분리

먼저 음반 정보를 constants/cartItems.ts 파일로 분리한다.

각 음반 데이터는 id, title, singer, price, img, amount 값을 가진다.

export interface CartItem {
  id: string
  title: string
  singer: string
  price: string
  img: string
  amount: number
}

 

이렇게 타입을 먼저 정의해두니 이후 Redux Slice나 컴포넌트에서 데이터를 사용할 때 훨씬 안정적으로 다룰 수 있었다.

2. Redux Store 구성

export const store = configureStore({
  reducer: {
    cart: cartReducer,
  },
})

Redux Toolkit의 configureStore를 사용해서 전역 Store를 만들었다.

<Provider store={store}>
  <App />
</Provider>

그리고 main.tsx에서 앱 전체를 Provider로 감싸 Redux Store를 연결했다.

이 설정을 통해 앱 내부 어디서든 Redux 상태에 접근할 수 있게 되었다.

3. cartSlice 설계

장바구니 상태는 다음 세 가지 값을 중심으로 구성했다.

interface CartState {
  cartItems: CartItem[]
  amount: number
  total: number
}
  • cartItems: 장바구니 음반 목록
  • amount: 전체 수량
  • total: 전체 금액

그리고 Redux Toolkit의 createSlice를 사용해서 장바구니 관련 액션들을 정의했다.

  • increase: 특정 음반 수량 증가
  • decrease: 특정 음반 수량 감소
  • removeItem: 특정 음반 삭제
  • clearCart: 장바구니 전체 삭제
  • calculateTotals: 전체 수량과 금액 계산

특히 decrease에서는 수량이 1보다 작아지면 해당 음반이 자동으로 장바구니에서 제거되도록 처리했다.

if (item.amount < 1) {
  state.cartItems = state.cartItems.filter(
    (cartItem) => cartItem.id !== action.payload,
  )
}

 

4. 총 수량과 총 금액 계산

장바구니의 전체 수량과 총 금액은 calculateTotals에서 계산했다.

Mock Data의 price 값이 문자열이었기 때문에 계산 시 Number(item.price)로 변환해주었다.

totals.amount += item.amount
totals.total += item.amount * Number(item.price)

그리고 컴포넌트에서는 useEffect를 사용해서 장바구니 목록이 변경될 때마다 자동으로 합계를 다시 계산하게 만들었다.

useEffect(() => {
  dispatch(calculateTotals())
}, [cartItems, dispatch])

 

5. 컴포넌트와 Redux 연결

컴포넌트에서는 useSelector로 Redux 상태를 가져오고, useDispatch로 액션을 실행했다.

const dispatch = useAppDispatch()
const { cartItems, amount, total } = useAppSelector((state) => state.cart)

수량 증가 버튼을 누르면 increase 액션이 실행된다.

onClick={() => dispatch(increase(item.id))}

수량 감소 버튼은 decrease, 제거 버튼은 removeItem, 전체 삭제 버튼은 clearCart를 실행하도록 연결했다.

6. UI 

UI는 Tailwind CSS를 사용해서 구성했다.

최종적으로는 다음과 같은 구조로 구현했다.

  • 상단 Navbar
  • 장바구니 아이콘과 전체 수량 표시
  • 음반 리스트
  • 음반 이미지, 제목, 가수명, 가격 표시
  • 수량 증가/감소 버튼
  • 개별 제거 버튼
  • 총 금액 표시
  • 전체 삭제 버튼

7. 배운 점

Redux Toolkit의 전체 흐름을 한 번에 경험할 수 있었다.

Mock Data 분리
→ Slice 생성
→ Store 등록
→ Provider 연결
→ useSelector로 상태 조회
→ useDispatch로 액션 실행
→ 상태 변경에 따라 UI 자동 반영

 

처음에는 Redux가 복잡하게 느껴질 수 있지만 Redux Toolkit을 사용하니 Slice 안에서 상태와 액션을 함께 관리할 수 있어서 구조가 훨씬 명확했다. 또한 장바구니처럼 여러 값이 서로 연결되어 있는 기능에서는 전역 상태 관리가 왜 필요한지 이해할 수 있었다.수량이 바뀌면 개별 음반의 amount뿐만 아니라 전체 수량과 총 금액도 함께 바뀌어야 한다. 이런 상태들을 한 곳에서 관리하니 UI와 데이터 흐름이 더 깔끔해졌다.