저번 강의까지의 작업으로
이 섹션이 거의 끝나가고 있습니다
참조나 대상간 데이터 전달방식 등에 대하여
많이 다루었습니다
그에 더해
이 섹션엔 포털도 포함되어 있습니다
그것을 바로 다음으로 다루어 보면서
이 섹션을 마무리 짓겠습니다
그렇다면 포털의 특징은 무엇이며
우리가 어떻게 사용할 수 있을까요?
포털에 대해 이해하기 위해
예시로 이런 모달을 들어봅시다
지금 여기서 이겼으니
이 모달을 분석해 보겠습니다
여기 보시면 대화상자(dialog) 요소가
이 DOM의 모든 위치에 삽입되어 있습니다
특히 끝에 있는 다른 HTML 요소들에 중첩되어 있습니다
그 이유는
ResultModal 컴포넌트가 JSX 코드의 일부로 출력되어
TimerChallenge 컴포넌트로 돌아가기 때문입니다
그래서 이 부분이 출력된 곳은
이 섹션 출력 위치와 같은 곳입니다
그래서 대화상자와 섹션이 같이 붙어 있습니다
이 부분이 섹션이고, 이부분이 대화상자입니다
시각적으로 봤을 때는
딱히 문제 될 것이 없습니다
하지만 기술적으로 더 맞는 방법은
페이지 제일 위에 보여지는 이 오버레이 요소가
바로 바디(body) 밑이나
혹은 이 디브(div) 안으로 출력된다면
div는 ID를 modal로 받는 것을 볼 수 있습니다
제가 실수로 프로젝트 초반에 추가하지 못했지만
이렇게 대화상자가 더 높은 층위에 있어야
더 직관적입니다
왜냐하면 이것의 시각적 모습을
HTML 구조의 해당 위치에 매핑하기 때문입니다
접근성으로도 더 좋을 수 있고
혹시 모를 형식 문제도 피할 수 있게 합니다
여기선 보이지 않지만
특정 상황에서는 깊게 중첩된 요소가
그 위에 다른 요소들에 묻혀 숨겨질 수도 있습니다
그렇기 때문에 우리는 컨트롤을 하거나
이 타이머 챌린지에 있는 모달 구성을 출력하는것이 좋겠습니다
그 컴포넌트를 그 쪽에서 사용하기 때문입니다
또한 그것의 JSX 코드를 이 페이지에 위치시키겠습니다
바로 이런 류의 문제들을
포털이 해결할 수 있습니다
이 특징을 사용하려면 가져오기를 위한 import가 필요합니다
react-dom 에서 가져와야 하는데
리액트 라이브러리 그 자체에서 가져오는것이 아니라
이 리액트 DOM 라이브러리 에서 가져오는 것입니다
둘은 같은 팀에서 관리 되고 있습니다만
근본적인 차이점은
리액트 라이브러리는 모든 환경에서 작동 가능한
함수와 기능만 노출합니다
리액트 네이티브로 네이티브 어플을 만들때 사용이 가능합니다
관련하여 더 알고싶다면
제가 마련한 별도 강의가 있으니 확인하셔도 좋습니다
반면 리액트 DOM 라이브러리에 포함된
몇 가지 함수와 기능은
결국 리액트가 DOM과 상호작용 하게 합니다
즉 브라우저에 렌더링된 웹사이트와 상호작용합니다
리액트 DOM이 노출하는 다른 기능이 필요한데
여기에 createPortal 함수를 만들겠습니다
말그대로 포털을 만들 때 사용합니다
포털의 의의는
이 컴포넌트에 렌더링이 될 HTML 코드를
DOM 내에 다른 곳으로 옮기는 것입니다
이렇게 하기 위해선 이 JSX코드를 감싸 주시고
createPortal을 이용하여 보내 줍니다
여기서 createPortal은 두번째 인수를 받는데
이 JSX 코드 뒤에 오게 됩니다
그래서 첫 번째 인수는 JSX 코드이며
이 createPortal의 두 번째 인수는 HTML 요소입니다
여기로 코드가 옮겨지게 됩니다
그래서 결국엔 이 코드를 렌더링해야 합니다
그리고 이런 요소가
우리의 인덱스 파일(Index.html)에 있어야 합니다
그래서 제가 그 파일에
ID로 modal을 받는 특수한 디브(div)를 추가하였습니다
이 모달을 이 div에 붙이기 위해서입니다
그렇게 하면 content에 너무 깊게 들어가지도 않고
바디의 루트(root)에 비교적 가까워집니다
그리하여 ResultModal에 있는
두번째 인수의 createPortal은
기본 브라우저 API로 선택해야 합니다
document.getElementByld를 사용하면 됩니다
제 경우 ID는 모달입니다
이 디브를 선택하면서 제가 추가한 ID입니다
여기 이 코드는
메인 파일이나 인덱스 파일에서 보던 것과 비슷합니다
여기에 createRoot 메소드가 있는데
이것 또한 HTML파일의 요소가 필요하며
여기에 리액트 앱이 렌더링됩니다
이제 여기서 똑같이
createPortal을 사용함으로써 똑같은 리액트 앱의
출력 위치를 다르게 설정합니다
이렇게 하면 완료됩니다
이제 이것을 저장하고 새로고침하여
타이머가 만료되길 둔다면
전과 같이 새 창이 뜨지만
개발자 도구로 점검했을때
이 대화상자가 여기 모달 디브 안에 있고
content 디브엔 없는 것을 확인할 수 있습니다
여기에 중첩되지 앖고
대신 이 모달 디브 안에 있습니다
그리고 여기 여러 개의 대화상자가 보이는 것은
타이머 챌린지가 여러 개이기 때문입니다
하지만 지금은 첫 번째 대화상자만 보여집니다
이렇게 포털의 기능을 다루어 보았습니다
포털은 이런 비슷한 상황에서 많이 쓰입니다
즉 JSX 코드 렌더링이
현재 어플에서 사용하고 있는 곳이 아니라
웹페이지의 다른 곳에 가야하는
모달이나 비슷한 시나리오가 있을 때
포털이 자주 사용되고 있습니다