Conversation
hyesngy
left a comment
There was a problem hiding this comment.
정말 고생 많으셨습니다! 👏🏻👏🏻👏🏻
이번 주 워크북을 통해 Redux Toolkit과 Zustand 두 가지 상태관리 라이브러리를 모두 다뤄보았습니다. 앞으로 프로젝트 복잡도나 규모에 따라 적절한 상태관리 도구를 선택할 수 있는 안목을 갖추게 되셨으면 좋겠습니다! 👍🏻👍🏻👍🏻
| import { configureStore } from "@reduxjs/toolkit"; | ||
| import cartReducer from "../slices/cartSlice"; | ||
| import modalReducer from "../slices/modalSlice"; | ||
|
|
||
| function createStore() { | ||
| const store = configureStore({ | ||
| reducer: { | ||
| cart: cartReducer, | ||
| modal: modalReducer, | ||
| }, | ||
| }); | ||
| return store; | ||
| } | ||
|
|
||
| const store = createStore(); | ||
| export default store; | ||
|
|
||
| export type RootState = ReturnType<typeof store.getState>; | ||
| export type AppDispatch = typeof store.dispatch; |
There was a problem hiding this comment.
현재 장바구니 데이터가 새로고침 시 초기화되고 있는데, Redux Toolkit의 redux-persist나 Zustand의 persist 미들웨어를 적용하여, 새로고침 후에도 장바구니 상태가 유지되도록 🚀Challenge 미션에 도전해 보시면 좋겠습니다!
| const Modal = () => { | ||
| const dispatch = useDispatch(); | ||
| const isOpen = useSelector((state) => state.modal.isOpen); |
There was a problem hiding this comment.
현재 미션 3에서 장바구니는 Zustand로 잘 관리하고 있지만, 모달은 아직 Redux로 관리하고 있어 혼재된 상태입니다.
Modal.tsx에서 useDispatch와 useSelector를 사용하여 Redux의 modalSlice를 참조하고 있고, PriceBox.tsx에서도 openModal 액션을 Redux로 디스패치하고 있습니다. 모달 상태 관리도 Zustand로 완전히 마이그레이션해야 합니다.
| function App() { | ||
| return ( | ||
| <Provider store={store}> | ||
| <Navbar /> | ||
| <CartList /> | ||
| <Modal /> | ||
| <PriceBox /> | ||
| </Provider> | ||
| ); | ||
| } |
There was a problem hiding this comment.
현재 미션 3의 App.tsx 에서 Redux의 Provider로 감싸고 있는데, 미션 3에서는 Zustand로 상태 관리를 전환했기 때문에 이 부분은 제거해야 합니다. 또한, store.ts, cartSlice.ts 등 Redux 관련 파일들이 여전히 남아있는데, 프로젝트 구조를 명확하게 하기 위해 해당 파일들도 제거하는 것을 권장합니다!
hyesngy
left a comment
There was a problem hiding this comment.
10주차 워크북까지 정말 긴 여정이었습니다.
그동안 모두 고생 많으셨습니다! 👏🏻👏🏻👏🏻 짧지 않은 기간동안 의미 있는 시간이 되었기를 바랍니다.
이제 기본 워크북은 모두 완주하셨지만, 11-12주차 워크북도 도전해보시길 추천드립니다! 11주차에서는 Vercel을 활용한 배포와 CI/CD 구성을 다루고, 12주차에서는 WebSocket을 이용한 실시간 통신과 Cypress를 활용한 E2E 테스트를 다룹니다.
앞으로도 꾸준히 학습하고 성장하시길 응원하며, 데모데이까지 화이팅 입니다! 👍🏻👍🏻👍🏻
| const useFetch = <T>(url: string, options?: AxiosRequestConfig) => { | ||
| const [data, setData] = useState<string | null>(null); |
There was a problem hiding this comment.
현재 useFetch에서 제네릭 <T>를 선언해놨지만 실제로는 활용하지 못하고 있는 상황입니다.
useState<string | null>(null)로 하드코딩되어 있어서 Homepage.tsx에서 useFetch<MovieResponse>로 호출해도 data의 타입이 string으로 고정되어 버립니다.
이로 인해 data?.results에 접근할 때 TypeScript가 올바른 타입 추론을 하지 못하고, 런타임에서 예상치 못한 에러가 발생할 위험이 있습니다. 제네릭 타입 T를 활용하여 useState<T | null>(null)로 수정하면 호출하는 곳에서 지정한 타입(MovieResponse)이 제대로 반영되어 타입 안정성이 크게 향상될 것입니다!
| const useFetch = <T>(url: string, options?: AxiosRequestConfig) => { | |
| const [data, setData] = useState<string | null>(null); | |
| const useFetch = <T>(url: string, options?: AxiosRequestConfig) => { | |
| const [data, setData] = useState<T | null>(null); |
There was a problem hiding this comment.
현재 코드를 보면 10주차 워크북 미션인 검색 기능에 집중한 구조로 되어 있는데, 지난 미션이었던 영화 페이지와 통합하면 더 완성도 높은 영화 사이트가 될 것 같습니다!
There was a problem hiding this comment.
🚀Challenge 미션에 따라 프로젝트 전체의 성능 최적화나 UX 개선에도 도전해보세요! 코드 품질 측면에서도 중복 제거, 책임 분리, 예외 처리 개선 등을 통해 가독성과 유지보수성이 좋은 코드로 리팩토링 해보면 어떨까요 😊
📝 미션 번호
9주차 Mission1,2,3,
📋 구현 사항
-modal을 통해 진짜 삭제할건지 나타냄
📎 스크린샷
✅ 체크리스트
🤔 질문 사항