본문 바로가기
today,weekly I learn

zustnad 개별 구독 / store 구독

by rhdaud2 2025. 6. 16.

 

 

 

모달 상태 관리 코드를 리팩토링하다가, zustand에서 store를 어떻게 구독하는 게 더 좋은지 고민하는 과정이 있었다.

공식 문서에도 있는 내용이었으나 구현에 급급해서 공부가 소홀했다

 

// stores/modalStore.ts
import create from 'zustand';

interface ModalState {
  isOpen: boolean;
  open: () => void;
  close: () => void;
}

export const useModalStore = create<ModalState>(set => ({
  isOpen: false,
  open:  () => set({ isOpen: true }),
  close: () => set({ isOpen: false }),
}));

이건 모달 상태를 간단하게 zustand로 전역관리 하는 modal 전용 store인데 (공용 modal 컴포넌트와 묶어서 사용중)

 

 

기존에는 간략하게 작성하려고 아래와 같이 사용했으나

const { isOpen, open, close } = useModalStore();

 

이건 store 전체를 구독하는 비효율적 패턴이라고 한다, - store 내 다른 값이 바뀌어도 이 컴포넌트가 리렌더링되기 때문.

특히 규모가 커질수록 불필요한 렌더가 많아져서 퍼포먼스에 악영향을 줄 수 있다고한다

 

(2) selector로 필요한 값만 개별 구독 – 권장 패턴

const isOpen = useModalStore(state => state.isOpen);
const { open, close } = useModalStore(state => ({
  open: state.open,
  close: state.close,
}));

 

이와 같이 개별구독할 시 isOpen이 바뀔 때만 리렌더링이 발생한다.

(open/close는 변하지 않는 함수이니 한번에 불러와도 성능상 문제는 없을 것으로 예상된다

 

 

(3) 여러 값을 한 번에 selector로

const { isOpen, open, close } = useModalStore(state => ({
  isOpen: state.isOpen,
  open: state.open,
  close: state.close,
}));

 

이 방식은 store 전체 구독보단 낫지만, selector 안의 값 중 하나라도 바뀌면 매번 새로운 객체가 리턴되어(참조값 변화), 해당 컴포넌트가 리렌더된다.

 

 

=> 상태(state) 값은 개별 selector / 액션(action) 함수들은 묶어서 selector로 한 번에 

 

 

참고 문서