
이번 게시글에서는 Next JS 14에서 react-portal을 사용하여 custom hook을 어떻게 적용할 수 있는지에 대해서 알아보겠습니다.
(개발환경 : NextJS 14, Typescript, tailwind-CSS)
부모 컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링하는 최고의 방법이다.
공식 문서에 위와 같이 설명되어 있습니다.
간단하게 말하자면 리액트 포탈을 사용하면 우리가 미리 지정한 위치에 모달이 렌더링된다.정도로 이해하고 넘어갑니다.
(부모-자식관계는 유지한채로 부모 바깥에 렌더링할 수 있게 해줍니다.)

오늘의 희생양은 회원가입에 필요한 다음 Kakao 주소검색 API입니다.
편하게 가이드 주는대로 새창으로 띄우고 사용하고 싶지만 react-portal도 공부해야하니 슬프지만 오늘은 react-portal을 사용한 모달로 적용하기로 했습니다.

NextJS 14에 React Portal을 적용하면서 가장 많이 찾아봤던 내용입니다. 주로 React에 적용한 글들을 많이 볼 수 있었는데 React에서는 index.html에 <div id = "portal">을 넣고 있었습니다.
App 디렉터리를 세팅되어 있는 우리의 NextJS 14에는 슬프게도 index.html파일은 존재하지 않습니다. 구글링 결과 _document.js과 최상단에 있는 layout.tsx가 비슷한 역할을 하고 있는 것 같습니다.
파일을 새로 만드는건 떨리는 일이니 저는 최상단의 layout.tsx에다가 포탈 구멍을 만들었습니다.
(_document.js에 해도 가능합니다.)

이제 포탈 컨테이너를 만듭니다. 위 이미지처럼 useModal.tsx 이라는 hook을 만들고 그 안에 원하는 컴포넌트를 넣어서 모달을 재사용하려고 합니다.
import { createPortal } from 'react-dom';
... return
createPortal(원하는 모달 UI, 포탈 구멍 연결)
기본적으로 위와 같이 createPortal을 불러온 다음 createPortal의 첫번째 인자에 모달 컨테이너의 UI를 넣어줘야합니다. 두번째 인자에는 아까 만들었던 포탈 구멍의 위치를 잡아줍니다.

여기서 주의해야할 것은 NextJS의 경우 Hydration 에러가 발생할 수 있습니다. 이 코드에서는 useEffect()를 통해 렌더링이 끝난 이후 document.querySelector를 사용하여 아까 만든 포탈 구멍의 위치를 dom에게 반환하였습니다.
useModal.tsx는 모달을 여는 함수, 닫는 함수, 모달 포탈을 return 하여 원하는 곳에서 불러와서 모달을 넣고 열고 닫을 수 있도록 만들었습니다.

회원가입 페이지에서 다음 주소찾기 API를 모달로 만들 것이므로 해당 폼에서 불러왔습니다.
(❗️ hook을 사용하고 있기 때문에 ‘use client’ 에서 불러와야합니다.)


daum-postcode API에서 주소가 Input에 들어오면 모달이 자동으로 닫히도록 설정했습니다.

그리고 도로명 주소 검색하기 버튼을 누르면 모달이 열리도록 설정했습니다.
<ModalPortal>로 원하는 컴포넌트를 감싸준다

