ContextAPI와 상태 관리 라이브러리의 목적
-
이번 글은 완성 모달에 영향을 미치지 않는, 최종 코드에서 삭제된 부분에 대한 내용이지만 그 과정을 적어두고자 작성하는 챕터로 방향성을 잘못 잡으면 코드가 얼마나 산으로 갈 수 있는지를 느껴본다.
내가 창조한 요상한 기능은 Local 모달 이라고 부르기로 한다. 먼저 이 상황이 발생한 이유는 최종이라고 생각한 모달이 `Jotai`로 했을 때와 어떤 차이가 있는지 체감이 되지 않았기 때문이다. 분명 뷰와 관련된, 특히 재사용 가능한 UI를 전역으로 관리할 때에는 `Context`가 낫다고 들었고, 공감이 되는 듯하면서도 정확히 설명할 수 없었다.
`Context`의 역할을 느끼기 위해 모달을 부분적으로 사용하는 상황을 가정하여 재사용할 수 있는 로직을 구현해 보자.
const renderModal = useCallback(
(portalContainer?: MutableRefObject<HTMLDivElement | null>) => {
const modal = modals.find((modal) => modal.id === modalId);
return (
modal &&
(modal.isLocal && portalContainer ? (
<ModalPortal portalContainer={portalContainer.current}>
<LocalModal modal={modal} onClose={closeModal} />
</ModalPortal>
) : (
<ModalPortal>
<Modal modal={modal} onClose={closeModal} />
</ModalPortal>
))
);
},
[modals, modalId, closeModal],
);
원하는 경우에만 로컬 영역에 한정되게 열리므로 로컬 모달이라 칭했다. `modal state`에 `isLocal` 선택 옵션을 추가하고, 유무에 따라 다른 모달을 렌더링 할 수 있도록 전체적으로 수정한다. `renderModal`은 `portalContainer`를 선택적으로 받을 수 있게 되었다. 하지만 `LocalModal` 레이아웃도 별도로 필요하고 여러모로 복잡해졌다. 원하는 대로 구현되지만 이 코드를 볼 때마다 냄새난다는 소리를 들을 것 같았다.
온갖 테스트를 해보고 나서야 어떤 상황에서 ContextAPI와 Jotai를 구분해 사용할까? 에 대해 다시 생각해 볼 수 있었다.
상태를 전역으로 공유하다가 부분적으로 독립적인 상태 공유가 필요할 때
모달을 예를 들면 전역으로 `modals` 상태를 공유하다가 특정 컴포넌트부터 그 하위 자식 컴포넌트에는 독립적인 `modals` 상태를 갖고 싶다면 모든 로직은 동일하기 때문에 `modals`상태만 분리하면 된다. 꼭 모달이 아니더라도 상태와 로직을 기준으로 생각해 보면 이해가 쉽다. 똑같은 상황을 `ContextAPI`와 `Jotai`로 비교해 보자.
ContextAPI
Jotai
`Jotai`의 `1번` 방법은 atom을 생성하고 별도의 이름을 부여하면서 관리해야 하는 atom이 늘어나게 된다. `2번` 이 해결책이 될 수 있지만, id와 같은 구분값이 필요하고 구분된 상태를 공유하는 컴포넌트끼리는 동일한 id를 알아야 하므로 신경 쓸 일이 많아진다. `3번`은 store가 모달 상태 외 다른 상태들을 함께 관리 중이라면 부분적으로 Provider로 감쌌을 때, 다른 상태에 접근할 수 있도록 또 다른 처리를 해주어야 한다.
전역 상태 관리 도구로 Jotai를 쓰고 있기 때문에 Context로 모달을 관리하게 되었을 때의 확실한 장점을 얻고 싶었다. 그렇지 않으면 굳이 여러 가지로 나누어 관리할 필요가 없기 때문이다. 그래서 간단함을 떠나 무언가 다른 점이 있을 것 같았다. 컨텍스트의 특징과 함께 다시 생각해 보자.
처음에는 모달 같은 UI 요소는 비슷한 로직으로 재사용하는 경우가 많고, 화면과 관련된 상태라 독립적인 라이프사이클이 더 적합하다고 생각했다. 하지만 최종 완성 코드에서 어떤 상태 관리 방법을 써도 `useModal` 커스텀훅으로 분리하는 것은 동일했기 때문에 독립적인 라이프사이클의 장점은 활용하지 않게 되었다.
그래서 조금은 뻔하지만 가장 큰 장점을 3번이라고 결론지었다. 모달과 같은 UI는 현재 진행 중인 프로젝트뿐만 아니라 다른 프로젝트에서도 많이 사용되는 요소로 다음에 다른 프로젝트를 하더라도 또 사용하게 될 가능성이 높다. 그렇기 때문에 외부 라이브러리에 의존하지 않고, 미리 추상화된 UI 컴포넌트는 React로 만드는 어떤 프로젝트에서도 재사용이 가능하다는 점은 큰 장점으로 느껴진다.
무엇이든 이유 없이 쓰지 말자!라는 생각으로 돌고 돌았지만 이 차이를 구분해내지 못했다면 나는 이 프로젝트에 Jotai를 쓰겠다고 생각한 순간부터 어떤 상황에서도 atom을 만들어 관리했을 것이다. 이전 글에서 말했듯이 만들어진 기능을 가져다 쓸 때에는 어떤 불편함을 해소하기 위해 만들어졌을까를 한 번 더 고민해 보면 좋은 것 같다. 이제 개운한 마음으로 남은 챕터에서 모달 비동기 처리를 완성해 본다.
React 전역 Modal 추상화 정복기 - 마지막 (0) | 2024.04.16 |
---|---|
React 전역 Modal 추상화 정복기 - (5) (1) | 2024.04.14 |
React 전역 Modal 추상화 정복기 - (3) (0) | 2024.04.13 |
React 전역 Modal 추상화 정복기 - (2) (2) | 2024.04.13 |
React 전역 Modal 추상화 정복기 - (1) (2) | 2024.04.13 |