전역 모달 추상화 정복기

React 전역 Modal 추상화 정복기 - 마지막

뎁희 2024. 4. 16. 12:02

모달 레이아웃 컴포넌트 추상화로 템플릿 모듈화 하기

 

-

지금까지 반복적으로 사용된 UI 요소들을 새로운 모달이 추가될 때마다 템플릿으로 사용할 수 있는, 재사용 가능한 레이아웃 컴포넌트로 분리한다.


1. 기본 구조

return (
    <div className={cx('backdrop')} onClick={closeModal}>
		//모달
    </div>
);

단순하게 배경을 클릭하면 닫히는 div와 렌더링 되는 모달 컴포넌트를 children으로 받는다.


2. Overlay 분리

`Overlay`처럼 배경을 누르면 닫히는 기능은 `Bottom Sheet`등에서도 활용될 수 있어 분리하고, 내부 children도 Container로 분리했지만 이 단계에서는 큰 의미가 없었다.

 

개선

`<ModalContainer />`는 분리하지 않는 것으로 1차 개선했다.


3. 작게 분리하고 모듈화 하기

보통 모달 내부 콘텐츠 레이아웃을 분리할 때 `Header / Body / Footer`로 구분한다. 처음엔 이 구조를 적용했었는데 Footer에는 `확인/취소`와 같은 버튼을 두었을 때 문제가 있었다.

 

문제

프로젝트에서 겪었던 상황은 `Body`의 내용이 form인 경우였다. form 태그를 사용하게 되면 form 태그의 자식으로 있는 버튼을 통해 onSubmit이 이루어지는데 이를 처리하기 위해서는 `Footer`를 `Body`의 children으로 받아야 했다. 사실 크~게 상관은 없는 문제지만 FooterBody안에 있는 것이 어색하게 느껴져 조금 더 범용적으로 사용할 수 있는 구조를 원했다.

 

해결

코드 변경 없이 컴포넌트명을 변경해 사용 목적을 나타내는 방법으로 개선했다. 기존 Body를 Content로 바꿔서 모달의 구조를 `Header / Content`가 되도록 했다. 버튼을 포함한 콘텐츠 설계는 `<ModalContent />`에 작성한다. 기존 Footer 역할을 대신하는 `<ModalButtonGroup />`은 상황에 맞게 배치하여 사용할 수 있다. 


✨ 결과

레이아웃을 모듈화하여 사용하게 되면서 어떤 모달을 만들게 되더라도 레이아웃 컴포넌트만 import 하여 `Header / Content`구조에 맞추어 설계하면 된다. 레이아웃 컴포넌트들은 모달의 상태에 의존하지 않고 독립적이기 때문에 모달 상태나 로직에 영향을 주지 않고 수정할 수 있다.

 

추가로 모달마다 조금씩 디자인이 달라질 수 있는 점을 고려해 `styleType`이라는 속성을 추가했다. 타입에 따라 class를 동적으로 추가해 동일한 설계, 다른 UI의 모달을 손쉽게 만들 수 있다.