프로젝트 리팩토링 중 모달 부분을 리팩토링 했던 과정입니다.
//page.jsx
export default function Page(){
const [isOpen, setIsOpen]=useState(false);
const handleOpenModal=()=>{setIsOpen(true)}
return(
<div>
{isOpen && <Modal>모달이징</Modal>}
</div>
)}
기존에는 이렇게 isOpen의 값을 변경해서 모달을 열고 닫는 방식으로 페이지에서 모달을 관리했습니다. 하지만 이 방식은 모달이 1~2개 정도까지는 괜찮은데 모달이 여러개가 되면 관리해야 되는 상태도 많아지고 상태 변경 함수도 늘어나면서 관리가 어려웠습니다.
우선 처음에 진행했던 방식은 관련된 상태들을 객체로 묶어서 하나로 관리하는 방법을 적용했다.
이 상태에서 모달을 열고 닫을 때는 객체에서 해당 모달 상태만 변경해주면 됩니다.
위의 문제 해결을 위해서 useReducer를 적용해서 상태 변경 과정에서 반복적이고, 길어지는 코드를 사용전에 정의해주고, 사용할 때는 간단하게 사용할 수 있다.
//사용할 액션을 객체로 만들어둔다.
const action={
close:'close',
openWithdrawal:'openWidthdrawalModal',
openEmail:'openEmailModal'
}
dispatchModalState(action.openEmail);
이렇게 reducer로 상태변경을 미리 정의를 해두니 사용할때는 간단했지만 page에서 모달 관리를 위해서 기존 보다 더 많은 코드를 작성해야 하는 것 같았다. 그리고 이 페이지에서는 모달 상태가 4개라서 적용하는게 더 이득이였지만 1~2개와 같이 모달 수가 적다면 페이지마다 모달 관리를 위해 객체를 만들고 reducer를 만드는 것은 불필요해 보였다.
위와 같은 방식들은 모달을 사용하는 page에서 매번 관련 상태를 만들어줘야한다. 이 부분을 해결하기 위해 모달 관련 컴포넌트를 만들어서 상태를 컴포넌트 내에서 관리하도록 했다. 이것으로 페이지에서는 모달 상태를 관리 할 필요가 없어졌다.
//Page.jsx
export default function Page(){
return (
<ModalTriggerButton
ModalContent={
<ModalBasic onClickYes={handleDeletePlan} onClickNo={onClickNo} confirmSentense="삭제 하기">
정말 해당 계획을 삭제하시겠습니까 ?
</ModalBasic>}>
<span>삭제</span>
</ModalTriggerButton>
)
}
실제 페이지에서는 이런식으로 사용할 수 있다. 이런 방식으로 구현을 하니 페이지에서는 모달 관련 상태를 선언할 필요가 없고 컴포넌트 하나에 해당 모달과 관련된 내용을 모아 놓아서 어떤 내용의 모달이 나올지 알 수 있지만 코드를 보면 가독성이 떨어진다. 컴포넌트 이름과 안 맞게 Trigger 역할만 하는 것이 아니라 모달 내용도 받아서 띄워주고 있고, 어떤 부분이 trigger 역할을 하는 지도 알아보기 어렵다.
관리를 편하게 하기 위해서 컴폰넌트 하나에 묶었지만 컴포넌트 하나가 너무 많은 역할을 하는 것 같았고 분리가 필요하다고 생각했다. 그래서 compund 패턴을 적용해서 역할에 따라서 컴포넌트의 분리를 진행했다.
이 컴포넌트을 보면 컴포넌트 내에서 상태를 공유를 위한 context, 그리고 Provider역할을 위한 Main 컴포넌트, 모달을 열고 닫는 trigger역할을 할 Trigger 컴포넌트, 모달 내용을 받아줄 ModalContent 컴포넌트가 있다.
위 컴포넌트 형태는 compound 패턴을 적용해서 각 역할을 분리했습니다. 이런 식으로 만드니 위와 같이 관련 컴포넌트를 한번에 볼 수 있지만 어떤 역할을 하는지 확실하게 분리를 할 수 있었다.
모달과 관련해서 2023년에 popoverAPI가 나왔는데 이것을 실제 적용해보고 싶었지만 프로젝트에 적용하기에는 아직 이른 것 같아서 나중으로 미루었다.
popoverAPI를 적용하면 기존에 개발자가 작성해야 했던 코드에 대해서 많은 부분을 제거할 수 있을것 같다.
팝오버 소개
mdn에도 설명이 있지만 더 잘 설명해주는 블로그 글이 있다.
그리고 아직 적용이 안되는 브라우저가 많아서 polyfill적용이 필요하다.
popover-polyfill
리팩토링 야무지네요 👍🏻