Loading the catalog…
Loading the catalog…
팀 코드를 보다가 로그인 유저 정보와 약관 모달 노출 여부를 zustand로 관리하는 구조를 알게 되어 정리합니다. 아래 코드는 구조를 설명하기 위해 새로 작성한 예제입니다. 전체 흐름 로그인 요청이 성공하면 응답의 유저 정보를 스토어에 저장합니다. 유저 정보를 저장하는 시점에 약관 동의 여부를 확인해 약관 모달을 열지 정합니다. 약관 동의 요청이 성공하면 응답으로 받은 유저 정보를 다시 저장하고, 약관 모달을 닫으면서 환영 모달을 엽니다. 스토어 구성 // authStore.ts import { create } from 'zustand'; import { useModalStore } from './modalStore'; interface User { id: number; name: string; termsAgreed: boolean | null; } interface AuthState { user: User | null; isUserLoading: boolean; setUser: (user: User | null) => void; logout: () => void; } export const useAuthStore = create<AuthState>(set => ({ user: null, isUserLoading: true, setUser: user => { set({ user, isUserLoading: false }); // 약관 미동의 상태면 약관 모달 노출 useModalStore.getState().setTermsVisible(user?.termsAgreed === null); }, logout: () => set({ user: null }), })); // modalStore.ts import { create } from 'zustand'; interface ModalState { termsVisible: boolean; welcomeVisible: boolean; setTermsVisible: (visible: boolean) => void; closeModal: (type: 'terms' | 'welcome') => void; agreeTerms: () => void; } export const useModalStore = create<ModalState>(set => ({ termsVisible: false, welcomeVisible: false, setTermsVisible: visible => set({ termsVisible: visible }), closeModal: type => set(type === 'terms' ? { termsVisible: false } : { welcomeVisible: false }), agreeTerms: () => set({ termsVisible: false, welcomeVisible: true }), })); isUserLoading 을 처음에 true 로 두고 setUser 가 호출될 때 false 로 바꾸는 부분이 눈에 띄었습니다. 유저 정보가 아직 없는 상태와 로그인하지 않은 상태를 구분할 수 있어서, 첫 렌더링에서 화면이 깜빡이는 것을 막는 데 쓸 수 있습니다. 요청은 React Query, 결과는 zustand 로그인과 약관 동의는 값을 조회하는 요청이 아니라 상태를 바꾸는 요청이라 useMutation 을 씁니다. 성공 콜백에서 응답의 유저 정보를 setUser 에 넘깁니다. const handleAgreeTerms = () => { agreeTermsMutation(undefined, { onSuccess: res => { setUser(res.data ?? null); // 동의한 내용을 유저 정보에 반영 agreeTerms(); // 약관 모달 닫고 환영 모달 열기 }, }); }; useMutation 의 결과는 그 훅을 쓴 컴포넌트 안에만 있어서, 다른 화면에서도 같은 유저 정보를 쓰려면 전역 저장소에 넣어야 합니다. 그래서 조회 데이터는 React Query, 요청 결과를 앱 전체가 공유해야 하는 값은 zustand로 나눠서 쓴 구조입니다. 모달 닫기 처리 공통 모달 컴포넌트는 닫기 버튼과 ESC 키 모두 같은 핸들러를 거칩니다. 먼저 모달 내부 상태를 바꿔 사라지는 연출을 보여주고, 300ms 뒤에 스토어 상태를 닫습니다. const handleClose = useCallback(() => { setIsVisible(false); setTimeout(() => closeModal(modalType), 300); }, [closeModal, modalType]); useCallback 으로 핸들러를 고정해서 ESC 키 이벤트가 렌더링마다 다시 등록되지 않게 하고, 언마운트 때 이벤트를 해제합니다. 이 구조의 장단점 장점은 이렇습니다. 훅 밖에서도 getState() 로 접근할 수 있어서 요청 콜백이나 다른 스토어에서 상태를 바꾸기 쉽습니다. 모달 컴포넌트가 props를 거치지 않고 스토어만 보고 열리고 닫힙니다. 아쉬운 점은 이렇습니다. 새 모달을 추가하려면 스토어의 상태와 closeModal 의 타입을 같이 고쳐야 합니다. activeModal 하나로 관리하면 분기가 늘지 않습니다. 서버에서 받은 유저 정보가 스토어에도 있어서, 서버 데이터와 어긋나지 않도록 갱신 지점을 관리해야 합니다. 주의할 점 스토어의 유저 정보는 화면을 분기하는 용도입니다. 약관 동의 같은 필수 조건을 강제하려면 서버가 미동의 상태를 거절해야 하고, 클라이언트 모달은 안내 역할만 합니다. 정리 요청은 React Query의 useMutation , 요청 결과와 UI 상태는 zustand로 분리한다. isUserLoading 으로 유저 정보를 아직 모르는 상태를 구분한다. 서버 데이터와 스토어 값이 어긋나지 않도록 유저 정보를 갱신하는 지점을 정해 둔다.
What RADAR observed and classified to build this opportunity. It is what the source published, not a verification that the offer is still active.
유저 상태와 모달 UI 상태를 zustand로 관리하는 구조. 팀 코드를 보다가 로그인 유저 정보와 약관 모달 노출 여부를 zustand로 관리하는 구조를 알게 되어 정리합니다. 아래 코드는 구조를 설명하기 위해 새로 작성한 예제입니다. 전체 흐름 로그인 요청이 성공하면 응답의 유저 정보를 스토어에 저장합니다. 유저 정보를 저장하는 시점에 약관 동의 여부를 확인해 약관 모달을 열지 정합니다. 약관 동의 요청이 성공하면 응답으로 받은 유저 정보를 다시 저장하고, 약관 모달을 닫으면서 환영 모달을 엽니다. 스토어 구성 // authStore.ts import { create } from 'zustand'; import { useModalStore } from './modalStore'; interface…
Open source