로그인에 성공하면, 응답 데이터로 access token과 userId를 받는 상황이다. userId는 글을 포스팅 하기 위한 body의 인자로 사용되며, 글을 포스팅 하는 페이지는 로그인 페이지와는 다른 페이지이기 때문에 나는 이 userId 값을 zustand로 전역 상태 관리 하고 있었다.
코드를 살펴보도록 하자.
import { create } from "zustand";
interface IUseUserIdStore {
userId: number | null;
setUserId: (userId: number) => void;
}
const useUserIdStore = create<IUseUserIdStore>((set) => ({
userId: null,
setUserId: (userId: number) => set(() => ({ userId: userId })),
}));
export default useUserIdStore;
간단한 전역 상태관리 코드이다. userId는 초기에 null로 설정 되어 있으며, setUserId함수는 로그인 성공시 실제 API 응답 데이터의 userId 값을 setUserId의 인자로 전달하여 상태를 업데이트 하는 기능을 한다.
콘솔에 출력함으로 userId를 계속해서 체크하고 있었다. 로그인 성공이 확인되었을 때에, userId는 정확한 값이 출력되었지만, 페이지 새로 고침시에 userId가 초기화가 되어버려 null이 출력되는 문제가 발생했다.
대부분의 전역 상태 관리 라이브러리와 마찬가지로 Zustand는 상태를 메모리에 유지한다. 페이지가 새로 고쳐지면 JavaScript 환경이 다시 초기화되어 모든 메모리 내 상태(Zustand store포함)가 재설정되기 때문에 userId에 null이 출력이 되었던 것이었다.
이를 해결하기 위해 Zustand의 persist를 이용했다. persist는 전역 상태 관리 라이브러리의 기능 중 하나로, 상태의 지속성을 관리하는 데 사용된다. 상태의 지속성이란, 브라우저가 재시작되거나 페이지가 새로고침될 때도 어플리케이션의 상태를 유지하는 것을 의미한다. persist 기능을 사용하면 특정 상태를 로컬 스토리지 같은 저장 공간에 저장하여, 어플리케이션이 재시작되어도 그 상태를 복원할 수 있다.
import { create } from "zustand";
import { persist } from "zustand/middleware";
interface IUseUserIdStore {
userId: number | null;
setUserId: (userId: number | null) => void;
}
const useUserIdStore = create(
persist<IUseUserIdStore>(
(set, get) => ({
userId: null,
setUserId: (userId: number | null) => set(() => ({ userId: userId })),
}),
{
name: "userIdStorage",
}
)
);
export default useUserIdStore;
로그아웃 시에는 storage를 clear하고, userId 값을 null로 변경해야 로그아웃 후에 storage에 남아 있는 userId를 초기화할 수 있다.
const { setUserId } = useUserIdStore();
const clearUserIdStorage = useUserIdStore.persist.clearStorage;
const handleSignOut = (): void => {
if (window.confirm("로그아웃 하시겠습니까?")) {
alert("로그아웃 되었습니다.");
} else {
alert("취소합니다.");
return;
}
setUserId(null);
clearUserIdStorage();
setLoggedInFalse();
router.refresh();
};
};
로그인 상태를 유지하기 위해 Zustand의 persist 미들웨어를 사용하여 userId를 storage에 저장함으로써 페이지 새로고침 후에도 상태가 유지되도록 했다. 이로 인해 애플리케이션의 UX가 개선되고, 상태 관리의 지속성이 확보되었다. 이 경험은 단순한 코드 변경으로 중요한 사용자 인터페이스 문제를 해결할 수 있음을 보여주며, 상태 관리의 중요성과 효과적인 해결 방법에 대한 깊은 이해를 제공한다.