Portal
react portal이란?
글을 시작하며
인턴하면서 처음보는 리엑트 문법이 있었다. 음… 뭐지? react 문법 왠만한건 다 알고 있다고 생각 했는데 아직 모르는게 더 있었나? 하는 마음에 시간을 내어 찾아봤다.
찾아보니 react에 portal이라는 문법이 있었고 이놈이 뭐하는 놈인지 어디다 쓰는 놈인지 확실히 알아두고 싶어 이 글을 쓰게 되었다.
portal이란?
react는 크게 다음과 같은 구조를 가지고 있다.
가장 큰 App component가 있고 그 밑에 차례대로 자식 컴포넌트들이 tree를 이루며 계층 구초를 가지고 있다. (App 컴포넌트 안에 내가 만든 컴포넌트가 들어가 있는걸 볼 수 있다.)
때문에 기본적으로 랜더링 구조가 부모가 랜더링 되면 그 부모에 속해있는 자식 컴포넌트들도 같이 랜더링 되는 구조이다.
이 구조는 개발할때 편하게 정리할 수 있지만 코딩을 하다보면 이런 계층 구조가 불편한 순간 반드시 오게 되어있다. tree의 자료구조를 기반으로 코딩을 하다보면 자식과 부모관계를 가지고 있지만 서로 다른 프로세스에서 랜더링이 되어야 할때가 반드시 온다. (실제로 나도 이런경우를 만나서 좀더 편하게 코딩하는 방법은 없을까 하고 찾아보다 이 글을 쓰게 되었다. )
portal은 이런 문제를 해결하는 문법이다.
portal을 간단하게 말해보자면 tree의 부모를 하나 더 만들어 서로 독립적인 흐름을 제어할 수 있게 만드는 것이다.
실제로 portal을 이용해 만든 컴포넌트들을 보면 아래의 그림처럼 APP 컴포넌트 밖에 선언되어 있으며 서로 부모-자식 관계가 아닌 모습을 볼 수 있다.
portal의 사용법
create-react-app의 default 프로젝트 기준으로 설명하겠다.
portal을 사용하기위한 순서는 다음과 같다.
1. public/index.html에 root 밑에 자신이 추가하고 싶은 컴포넌트를 랜더링할 장소를 지정한다
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="root"></div>
<!-- 여기! -->
<div id="myportal"></div>
</body>
자기가 tree의 부모를 어디에 만들고 싶은지 지정해주는 작업이다.
2. 랜더링을 하기 위해 1에서 추가한 위치에 랜더할 수 잇는 작업을 한다.
// src/myPortal.js
import ReactDOM from 'react-dom';
const MyPortal = ({ children }) => {
// 위에서 추가한 div의 id값을 써주기
const el = document.getElementById('myportal');
return ReactDOM.createPortal(children, el);
};
export default MyPortal;
default에 있는 index.js를 하나 더 따로 만들어 준다고 생각하면 될 것 같다.
3. portal로 만들고 싶은 컴포넌트를 작성한다.
// src/MyComponent.js
import React from 'react';
import './MyModal.css';
const MyComponent = () => {
return (
<div className="MyModal">
<div className="content">
<h3>이것은 모달</h3>
<p>궁시렁 궁시렁 내용입니다.</p>
<button>닫기</button>
</div>
</div>
);
};
export default MyComponent;