NextJS프로젝트를 진행하는 동안 에러처리와 같은 것들을 전부 그냥 div 또는 span과 같은 형태로 사용자에게 알려주도록 설정했었다. 하지만 이런식으로 구현하는 것은 사용자의 경험을 해치는 행위가 될 수 있다고 판단했다.
생각해 본 문제점
- 사용자가 오류를 직관적으로 파악하기 힘들다.(div, span사용의 남발로 에러메시지 출력이 눈에 띄지 않는다.)
- 에러처리는 거의 대부분의 페이지에서 사용되어야 하는데 단순히 div, span으로 표시하는 방법은 일관성이 없고, 코드의 가독성마저 해친다.
- 확장성이 너무 떨어진다. 새로운 페이지를 생성시키거나 기능을 추가하면 같은 코드가 반복될 수 있다.
결론적으로는 다른 많은 웹사이트에서 볼 수 있는 방법인 팝업창 기능을 이용해야 했다.
그러기 위해서는 Modal(원하는 내용을 화면에 띄어 표현하는 방법)을 구현해야 한다.
하지만 여기서 문제가 생겼다.
Modal을 css로 구현하는 과정에서 기존에 컴포넌트 요소들 때문에 코드짜기 굉장히 까다로워졌다. 또한 다른 라이브러리, 플러그인을 사용하고 싶지는 않았다.
이를 해결할 수 있는 방법을 찾아보니 "createPortal"이라는 react에서 사용할 수 있는 기능이 있었다.
그 기능은 부모 컴포넌트의 내부 DOM이 아니라, 미리 지정해둔 DOM에서 렌더링 할 수 있는 기능이다.
쉽게 말하면 내가 원하는 곳에 렌더링을 할 수 있게 해주는 것이다.
<Component {...pageProps} /> <div id="global-modal"></div>
원래라면 Component에 모든 page들이 들어가지만 portal을 써서 한마디 portal을 타듯이 다른 곳으로 modal을 빼버린 것이다.
위 코드와 같이 Component에 들어가는 것이 아니라 따른 div를 생성시켜서 이 div를 Modal로 만들 수 있었다.
import React, { ReactNode } from "react"; import ReactDOM from "react-dom"; interface ModalProps { open: boolean; onClose: () => void; children: ReactNode; } const Modal = ({ open, onClose, children }: ModalProps) => { if (!open) return null; return ReactDOM.createPortal( <> <div className="fixed bottom-0 left-0 right-0 top-0 z-20 bg-black bg-opacity-50" /> <div className="fixed left-1/2 top-1/2 z-20 -translate-x-1/2 -translate-y-1/2 bg-orange-500 p-9"> <button onClick={onClose}>모달 닫기</button> {children} </div> </>, document.getElementById("global-modal") as HTMLElement, ); }; export default Modal;
참고 및 출처 : https://han-py.tistory.com/598