leebaek

[React] Zustand로 전역 모달 관리하기 본문

웹/React

[React] Zustand로 전역 모달 관리하기

leebaek 2025. 5. 3. 13:25

 

■ 지금까지의 모달 관리 방법

■ zustand 전역 모달 관리 방법


 

안녕하세요.

이전 포스팅까지 zustand에 대해 알아보는 시간을 가졌습니다.

 

이번에는 zustand를 이용한 전역 모달을 관리하는 방법에 대해 포스팅 해볼겁니다 !

 


■ 지금까지의 모달 관리 방법 - 로컬 on, off 방식

이전까지는 모달을 사용하는 각 컴포넌트 안에서

- 모달 컴포넌트를 import 

- useState로 모달 상태를 관리

- 조건부를 사용한 모달창 띄우기

로 단순하고 직관적인 방법을 사용해왔습니다.

import { useState } from 'react';
import LoginModal from './LoginModal';

function Header() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    <>
      <button onClick={() => setIsOpen(true)}>로그인</button>
      {isOpen && <LoginModal onClose={() => setIsOpen(false)} />}
    </>
  );
}

 

이 방식을 사용할 경우

모달을 사용하는 컴포넌트마다 import Modal from '...' 구문을 작성해야하니

모달 수가 많을 수록 중복 코드가 늘어남을 알 수 있습니다.

 

뿐만 아니라 각 컴포넌트마다 별도의 useState를 사용하니

일관성이 떨어지고 예상치 못한 버그가 생길 수 있다는 문제가 있었습니다.


이렇게한 이유는 제가 생각할 수 있는 최선이었던 것 같습니다.

리액트를 시작한지 2개월이 됐는데, 다른 방법이 있다곤 생각을 못해본 것 같습니다. 🥵

 

최근에 기술 면접을 봤는데, 이 부분에 대해 질문해주시더군요.

" 왜 이런 방식을 사용했는지???" 🤥

 

전 당당하게

" 어 .. ?  이렇게 관리하는거 아닌가요 ㅋㅋㅋ ㅠㅠㅠ "

라고 말했습니다.

 

ㅎㅎ 면접은 망했지만~

다른 방법에 대해 고민해볼 수 있는 기회를 얻어답니다.


zustand로 전역 모달 관리 방법

zustand를 도입해서 모달을 하나의 전역 store에서 관리하면 어떨까요 ?

그리고, App.js 같이 최상위 컴포넌트 한곳에서만 모달을 렌더링하는 겁니다.

 

이렇게 하면 코드 중복도 줄이고 일관성도 생기겠죠!!

 

예시 코드를 한번 볼까요 ~


modalStore.js

store에선 현재 모달 상태와 열기, 닫기에 대한 상태변경을 관리합니다.

import { create } from 'zustand';

export const useModalStore = create((set) => ({
  currentModal: null, // 'login' or 'signup'
  openModal: (modal) => set({ currentModal: modal }),
  closeModal: () => set({ currentModal: null }),
}));

 

 


App.js

조건부에 맞게 모달을 렌더링해줍니다.

import React from 'react';
import { useModalStore } from './modalStore';
import LoginModal from './modals/LoginModal';
import SignupModal from './modals/SignupModal';
import HomePage from './HomePage';

function App() {
  const { currentModal, closeModal } = useModalStore();

  return (
    <>
      <HomePage />

      {currentModal === 'login' && <LoginModal onClose={closeModal} />}
      {currentModal === 'signup' && <SignupModal onClose={closeModal} />}
    </>
  );
}

export default App;

 

 

이전 방식은 모달이 필요한 컴포넌트마다 이 작업을 해주었죠 ? ( 중복코드 와르르 )


HomePage.js

모달을 띄우고 싶은 컴포넌트에선 간단하게 모달 상태만 바꿔주면 됩니다.

import React from 'react';
import { useModalStore } from './modalStore';

function HomePage() {
  const openModal = useModalStore((state) => state.openModal);

  return (
    <div>
      <h1>홈페이지</h1>
      <button onClick={() => openModal('login')}>로그인</button>
      <button onClick={() => openModal('signup')}>회원가입</button>
    </div>
  );
}

export default HomePage;

LoginModal.js

import React from 'react';

function LoginModal({ onClose }) {
  return (
    <div style={modalStyle}>
      <h2>로그인 모달</h2>
      <button onClick={onClose}>닫기</button>
    </div>
  );
}

const modalStyle = {
  position: 'fixed',
  top: '30%',
  left: '50%',
  transform: 'translateX(-50%)',
  padding: '20px',
  background: 'white',
  border: '1px solid #ccc',
  zIndex: 1000,
};

export default LoginModal;

 

zustand로 모달을 관리할 때의 장점은

1. 전역에서 상태를 쉽게 제어할 수 있다.

2. 불필요한 prop drilling 제거 가능하다.

3. 일관된 상태 관리가 가능하다.

4. 필요한 모달만 렌더링하니 성능이 최적화된다.

5. 컴포넌트가 독립적이라 유지보수가 쉽다.


 

이번 포스팅은 여기까지입니다.

저는 이 방식으로 코드 리팩토링하러 가겠습니다.. 총총 ㅋㅋ 😂