서론
React에서 모달과 같은 UI는 주로 useState로 상태를 관리하는 예시가 많다. 하지만 관리해야 하는 모달의 개수가 증가할수록 코드의 복잡해진다.
이번 글에서는 모달에 대한 상태 관리를 이야기해보려고 한다.
모달의 상태관리
모달의 상태를 관리하는 대상을 객체로 생각해 보면, 책임을 두 가지 정도로 정의해볼 수 있다.
- 모달의 표시(열림/닫힘) 상태를 알고 있다.
- 모달의 표시 여부를 변경할 수 있다.
이 책임을 기반으로 React에서 모달의 상태를 관리하는 방법을 살펴보자.
지역 상태
지역 상태 방식은 모달을 사용하는 컴포넌트에서 상태를 관리한다. 예시는 다음과 같다.
function Component() {
const [isOpen, setIsOpen] = useState(false);
const openModal = () => {
setIsOpen(true);
};
const closeModal = () => {
setIsOpen(false);
};
return (
<>
<button onClick={() => openModal()}>Open Modal</button>
<Modal isOpen={isOpen} onClose={() => closeModal()} />
</>
);
}
지역 상태 방식은 구현 방법이 간단한 이점이 있다. 하지만 한계점도 분명하다.
- 모달의 개수가 많아지는 경우 상태 관리의 복잡도가 증가한다.
- 요구사항에 따라 모달 상태를 관리하는 코드가 이동될 수 있다.
(예시) history 이동 간 모달 상태 유지 필요한 경우, 상위 컴포넌트로 코드를 이동시켜야 한다.)
1번의 경우 커스텀 훅으로 코드를 분리하여 해결할 수 있지만, 항상 모달의 표시 관련 코드와(isOpen, openModal, closeModal) 컴포넌트의 return 문에 JSX를 선언해야 한다.
2번의 경우 처음부터 최상위 컴포넌트에서 모달의 상태를 관리하여 해결할 수 있지만, props drilling 및 관심사를 분리하기 어렵다.
전역 상태
전역 상태 방식은 모달에 대한 상태를 전역 저장소 한 곳에서 관리한다. 예시로 토스의 overlay-kit 라이브러리 사용하면 다음과 같다.
import { overlay } from 'overlay-kit';
function Component() {
const handleButtonClick = () => {
overlay.open(({ isOpen, close, unmount }) => {
return <Modal isOpen={isOpen} onClose={close} onExit={unmount} />;
});
};
return (
<>
<button onClick={() => handleButtonClick()}>Open Modal</button>
</>
);
}
지역 상태 방식과 달리 모달에 대한 상태 관련 로직을 overlay 모듈에 위임한 것을 확인할 수 있다. 이러한 구조는 모달의 개수가 늘어나더라도 overlay 모듈로만 상태를 관리를 할 수 있어 코드의 복잡성을 줄인다. 또한 모달을 여는 이벤트에 선언적으로 모달 JSX를 전달할 수 있다.
하지만 위와 같이 구현된 전역 상태 방식은 모달에 전달되는 상태가 동적으로 갱신되지 않는 한계점이 있다. 이는 모달을 여는 시점의 상태를 주로 스냅샷 형태로 전달하기 때문이다.
예를 들어 아래 코드는 모달을 열고 count 값이 변경되어도 모달에 반영되지 않는다 (관련 이슈).
function Component() {
const [count, setCount] = useState(0);
const handleButtonClick = () => {
overlay.open(({ isOpen, close, unmount }) => {
return <Modal isOpen={isOpen} count={count} onClose={close} onExit={unmount} />;
});
};
return (
<>
<button onClick={() => setCount((p) => p + 1)}>Increase count</button>
<button onClick={() => handleButtonClick()}>Open modal</button>
</>
);
}
결론
React에서 모달 상태 관리는 생각보다 복잡하다. 그래서 단순화하기 위해 모달 상태 관리 라이브러리가 지속적으로 개발되고 있다고 생각한다.
마지막으로 최근 살펴보고 있는 모달 상태 관리 라이브러리를 추가로 공유하고 글을 마무리하려고 한다.
- https://github.com/toss/overlay-kit
- https://github.com/eBay/nice-modal-react
- https://github.com/desko27/react-call
- https://mantine.dev/x/modals/
긴 글 읽어주셔서 감사합니다.
댓글