Skip to content

Create Week 9 Mission1, 2, 3#111

Open
PocheonLim wants to merge 4 commits intomainfrom
pocheonLim
Open

Create Week 9 Mission1, 2, 3#111
PocheonLim wants to merge 4 commits intomainfrom
pocheonLim

Conversation

@PocheonLim
Copy link
Collaborator

📝 미션 번호

9주차 미션 1, 2, 3

📋 구현 사항

  • Redux tollkit을 이용한 장바구니
  • zustand로 구현

📎 스크린샷

bandicam.2025-05-26.14-26-03-925.mp4

✅ 체크리스트

  • Merge 하려는 브랜치가 올바르게 설정되어 있나요?
  • 로컬에서 실행했을 때 에러가 발생하지 않나요?
  • 불필요한 주석이 제거되었나요?
  • 코드 스타일이 일관적인가요?

🤔 질문 사항

Copy link
Member

@hyesngy hyesngy left a comment

Choose a reason for hiding this comment

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

정말 고생 많으셨습니다! 👏🏻👏🏻👏🏻

이번 주 워크북을 통해 Redux ToolkitZustand 두 가지 상태관리 라이브러리를 모두 다뤄보았습니다. 앞으로 프로젝트 복잡도나 규모에 따라 적절한 상태관리 도구를 선택할 수 있는 안목을 갖추게 되셨으면 좋겠습니다! 👍🏻👍🏻👍🏻

Comment on lines +20 to +58
const initialState: CartState = {
items: cartItems,
totalAmount: cartItems.length,
totalPrice: cartItems.reduce((total, item) => total + Number(item.price), 0),
};

const cartSlice = createSlice({
name: 'cart',
initialState,
reducers: {
increaseAmount: (state, action: PayloadAction<string>) => {
const item = state.items.find(item => item.id === action.payload);
if (item) {
item.amount += 1;
cartSlice.caseReducers.calculateTotals(state);
}
},
decreaseAmount: (state, action: PayloadAction<string>) => {
const item = state.items.find(item => item.id === action.payload);
if (item && item.amount > 1) {
item.amount -= 1;
cartSlice.caseReducers.calculateTotals(state);
}
},
removeItem: (state, action: PayloadAction<string>) => {
state.items = state.items.filter(item => item.id !== action.payload);
cartSlice.caseReducers.calculateTotals(state);
},
clearCart: (state) => {
state.items = [];
state.totalAmount = 0;
state.totalPrice = 0;
},
calculateTotals: (state) => {
state.totalAmount = state.items.reduce((total, item) => total + item.amount, 0);
state.totalPrice = state.items.reduce((total, item) => total + (Number(item.price) * item.amount), 0);
}
},
});
Copy link
Member

Choose a reason for hiding this comment

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

현재 cartSlice에서 calculateTotalscaseReducers로 호출하여 구현하셨는데, 이는 좋은 접근이지만 initialState에서 총합 계산 로직이 중복되고 있습니다.
initialState에서도 calculateTotals 로직을 재사용하도록 리팩토링하면 코드 중복을 제거할 수 있고, 계산 로직이 한 곳에 집중되어 유지보수성이 향상될 것 같습니다!

Comment on lines +1 to +13
import { configureStore } from '@reduxjs/toolkit';
import cartReducer from '../slice/cartSlice';
import modalReducer from '../slice/modalSlice';

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

export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch; No newline at end of file
Copy link
Member

Choose a reason for hiding this comment

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

현재 장바구니 데이터가 새로고침 시 초기화되고 있는데, Redux Toolkit의 redux-persist나 Zustand의 persist 미들웨어를 적용하여, 새로고침 후에도 장바구니 상태가 유지되도록 🚀Challenge 미션에 도전해 보시면 좋겠습니다!

Comment on lines +17 to +19
React.useEffect(() => {
calculateTotals();
}, [items, calculateTotals]);
Copy link
Member

Choose a reason for hiding this comment

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

현재 useCartStore에서 각 액션 함수들이 calculateTotals를 자동으로 호출하지 않아 CartPage에서 useEffect를 통해 수동으로 총합을 계산하고 있습니다. 이는 상태 업데이트와 총합 계산이 분리되어 일관성 문제가 발생할 수 있으므로, increaseAmount, decreaseAmount, removeItem, clearCart액션들이 실행될 때마다 자동으로 calculateTotals를 호출하도록 수정하면 더욱 안정적인 상태 관리가 가능할 것 같습니다!

Copy link
Member

@hyesngy hyesngy left a comment

Choose a reason for hiding this comment

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

10주차 워크북까지 정말 긴 여정이었습니다.
그동안 모두 고생 많으셨습니다! 👏🏻👏🏻👏🏻 짧지 않은 기간동안 의미 있는 시간이 되었기를 바랍니다.

이제 기본 워크북은 모두 완주하셨지만, 11-12주차 워크북도 도전해보시길 추천드립니다! 11주차에서는 Vercel을 활용한 배포와 CI/CD 구성을 다루고, 12주차에서는 WebSocket을 이용한 실시간 통신과 Cypress를 활용한 E2E 테스트를 다룹니다.

앞으로도 꾸준히 학습하고 성장하시길 응원하며, 데모데이까지 화이팅 입니다! 👍🏻👍🏻👍🏻

Copy link
Member

Choose a reason for hiding this comment

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

현재 컴포넌트들이 적절히 분리되어 재사용성이 좋게 구성되어 있습니다. 특히 MovieFilter, Input, SelectBox, LanguageSelector 등의 세분화된 컴포넌트 분리가 인상적입니다!

Comment on lines +1 to +14
import HomePage from "./pages/HomePage"
import MovieModal from "./components/MovieModal"

function App() {

return (
<>
<HomePage />
<MovieModal />
</>
)
}

export default App
Copy link
Member

Choose a reason for hiding this comment

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

현재 App.tsx에서 MovieModal을 최상위에서 항상 렌더링하고 있는데, 이는 모달이 닫혀있을 때도 DOM에 존재하며 불필요한 메모리를 사용하여 비효율적입니다.

예를 들어, {isOpen && <MovieModal />} 형태로 조건부 렌더링하면, 실제로 모달이 열려있을 때만 컴포넌트가 마운트되어 성능이 더 개선될 수 있을 것 같습니다!

또는, 단일 책임 원칙에 따라 모달을 사용하는 곳에서 직접 모달 상태를 관리하는 것도 고려해볼 수 있겠습니다.

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.

2 participants