이전 글 zustand 간단 사용법!
최근 긴급 공지 모달 기능을 리팩토링하면서 Zustand를 도입하게 되었습니다.
이 글은 기존 방식의 문제점과, 해당 문제점을 Zustand로 개선한 경험을 코드 중심으로 정리한 글입니다.
우선 긴급 공지 모달 기능은 다음 과정을 거쳐 렌더링되고 있었습니다.
// EmergencyNtcModal.tsx
useEffect(() => {
const isTodayHidden = localStorage.getItem(`emergency_${id}`) === getToday();
if (!isTodayHidden) {
fetchNoticeDetail(id).then((data) => setModalData(data));
setShow(true);
}
}, []);
useEffect, localStorage, api 호출 등 동일한 로직이 반복하게 됩니다.// store/useEmergencyNoticeStore.ts
interface EmergencyState {
emerNtcIds: number[];
modalStates: { [id: number]: boolean };
noticeData: { [id: number]: Data };
fetchNoticeList: () => Promise<void>;
fetchNoticeDetail: (id: number) => Promise<void>;
checkAndHideModal: (id: number) => boolean;
hideModalForDay: (id: number) => void;
}
상태와 행동(Action)을 하나의 store에서 모두 관리하게 만들었습니다.
// store 내부
fetchNoticeList: async () => {
const list = await fetchNoticeListFromServer();
const visibleIds = list
.filter((item) => !isHiddenToday(item.id)) // localStorage 체크
.map((item) => item.id);
set({ emerNtcIds: visibleIds });
},
checkAndHideModal: (id) => {
const today = getToday();
return localStorage.getItem(`emergency_${id}`) === today;
},
hideModalForDay: (id) => {
const today = getToday();
localStorage.setItem(`emergency_${id}`, today);
},
// DashBoard.tsx
const { emerNtcIds } = useEmergencyNoticeStore();
return (
<>
{emerNtcIds.map((id, index) => (
<EmergencyNtcModal key={id} ntcId={id} index={index} />
))}
</>
);
// EmergencyNtcModal.tsx
const { modalStates, noticeData, fetchNoticeDetail, hideModalForDay } = useEmergencyNoticeStore();
useEffect(() => {
fetchNoticeDetail(ntcId);
}, [ntcId]);
// store 내부
checkAndHideModal: (id) => localStorage.getItem(`emergency_${id}`) === getToday()
// 컴포넌트
useEffect(() => {
fetchNoticeDetail(id);
}, []);
localStorage, 비동기 로직, 상태 판단이 중앙 집중화되어 테스트 및 재사용성 향상되었습니다.modalStates로 상태를 명확하게 관리할 수 있게 되었습니다.이번 리팩토링을 통해 Zustand가 얼마나 직관적이고 유연한 도구인지 체감한 것 같습니다.
컴포넌트에 몰려 있던 비즈니스 로직을 store로 분리하면서 코드 유지보수성과 확장성 모두 개선된 것 같습니다.
zustand-persist로 localStorage도 store 내부에서 자동 관리 가능피드백은 언제든지 환영합니다!