<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ttp_dev.log</title>
        <link>https://velog.io/</link>
        <description>TTP 블로그</description>
        <lastBuildDate>Tue, 13 Feb 2024 18:26:41 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ttp_dev.log</title>
            <url>https://velog.velcdn.com/images/ttp_dev/profile/ba031091-ba17-47e4-aef6-7898d3721a84/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ttp_dev.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ttp_dev" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Next.js 14 - react portal을 사용하여 모달 만들기]]></title>
            <link>https://velog.io/@ttp_dev/Next.js-14-react-portal%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EB%AA%A8%EB%8B%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@ttp_dev/Next.js-14-react-portal%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC-%EB%AA%A8%EB%8B%AC-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Tue, 13 Feb 2024 18:26:41 GMT</pubDate>
            <description><![CDATA[<p>이번 게시글에서는 Next JS 14에서 react-portal을 사용하여 <code>custom hook</code>을 어떻게 적용할 수 있는지에 대해서 알아보겠습니다.</p>
<p>(개발환경 : NextJS 14, Typescript, tailwind-CSS)</p>
<h2 id="react-portal">React Portal</h2>
<p><strong><code>부모 컴포넌트의 DOM 계층 구조 바깥에 있는 DOM 노드로 자식을 렌더링하는 최고의 방법이다.</code></strong>
공식 문서에 위와 같이 설명되어 있습니다. </p>
<p>간단하게 말하자면 <code>리액트 포탈을 사용하면 우리가 미리 지정한 위치에 모달이 렌더링된다.</code>정도로 이해하고 넘어갑니다.
(부모-자식관계는 유지한채로 부모 바깥에 렌더링할 수 있게 해줍니다.)</p>
<h2 id="오늘의-희생양">오늘의 희생양</h2>
<p><img src="https://velog.velcdn.com/images/ttp_dev/post/099a4de2-b0ff-40ba-88b2-457389e431f2/image.png" alt="">
오늘의 희생양은 회원가입에 필요한 <code>다음 Kakao 주소검색 API</code>입니다.</p>
<p>편하게 가이드 주는대로 새창으로 띄우고 사용하고 싶지만 <code>react-portal</code>도 공부해야하니 슬프지만 오늘은 react-portal을 사용한 모달로 적용하기로 했습니다.</p>
<br>
---
## 1. 초기 환경세팅 (포탈 구멍 파기)

<p><img src="https://velog.velcdn.com/images/ttp_dev/post/69a8205c-4afe-488f-ad3e-a4c166a218e8/image.png" alt=""></p>
<p>NextJS 14에 React Portal을 적용하면서 가장 많이 찾아봤던 내용입니다. 주로 React에 적용한 글들을 많이 볼 수 있었는데 React에서는 <code>index.html</code>에 <code>&lt;div id = &quot;portal&quot;&gt;</code>을 넣고 있었습니다. </p>
<p>App 디렉터리를 세팅되어 있는 우리의 NextJS 14에는 슬프게도 <code>index.html</code>파일은 존재하지 않습니다.  구글링 결과 <code>_document.js</code>과 최상단에 있는 <code>layout.tsx</code>가 비슷한 역할을 하고 있는 것 같습니다. </p>
<p>파일을 새로 만드는건 떨리는 일이니 저는 최상단의 <code>layout.tsx</code>에다가 포탈 구멍을 만들었습니다.
(_document.js에 해도 가능합니다.)</p>
<br>

<hr>
<h2 id="2-creatportal을-사용해서-포탈-만들기">2. creatPortal을 사용해서 포탈 만들기</h2>
<p><img src="https://velog.velcdn.com/images/ttp_dev/post/04c8106c-ec7a-4354-92a0-026198a81da0/image.png" alt=""></p>
<p>이제 포탈 컨테이너를 만듭니다. 위 이미지처럼 <code>useModal.tsx</code> 이라는 hook을 만들고 그 안에 원하는 컴포넌트를 넣어서 모달을 재사용하려고 합니다.</p>
<pre><code>import { createPortal } from &#39;react-dom&#39;;

... return 
createPortal(원하는 모달 UI, 포탈 구멍 연결)</code></pre><p>기본적으로 위와 같이 createPortal을 불러온 다음 createPortal의 첫번째 인자에 모달 컨테이너의 UI를 넣어줘야합니다. 두번째 인자에는 아까 만들었던 포탈 구멍의 위치를 잡아줍니다.</p>
<p><img src="https://velog.velcdn.com/images/ttp_dev/post/a0437f5a-1ee7-4f8c-bd2e-f97f2093ece8/image.png" alt=""></p>
<p>여기서 주의해야할 것은 NextJS의 경우 Hydration 에러가 발생할 수 있습니다. 이 코드에서는 <code>useEffect()</code>를 통해 렌더링이 끝난 이후 <code>document.querySelector</code>를 사용하여 아까 만든 포탈 구멍의 위치를 dom에게 반환하였습니다.</p>
<p><code>useModal.tsx</code>는 모달을 여는 함수, 닫는 함수, 모달 포탈을 return 하여 원하는 곳에서 불러와서 모달을 넣고 열고 닫을 수 있도록 만들었습니다.</p>
<br>

<hr>
<h2 id="3-usemodal을-사용해서-모달-적용하기">3. useModal을 사용해서 모달 적용하기</h2>
<h3 id="1-사용하고자-하는-곳에서-usemodal을-import한다">1. 사용하고자 하는 곳에서 useModal을 import한다.</h3>
<p><img src="https://velog.velcdn.com/images/ttp_dev/post/e3a18ce3-07de-48fa-8bc4-033eb7147fa0/image.png" alt=""></p>
<p>회원가입 페이지에서 다음 주소찾기 API를 모달로 만들 것이므로 해당 폼에서 불러왔습니다.
(❗️ hook을 사용하고 있기 때문에 ‘use client’ 에서 불러와야합니다.)</p>
<br>

<h3 id="2-openmodal-closemodal-modalportal을-가져온다">2. openModal, closeModal, ModalPortal을 가져온다.</h3>
<p><img src="https://velog.velcdn.com/images/ttp_dev/post/85de9b0b-3724-4020-a1a4-e1c711a7f3a7/image.png" alt=""></p>
<br>

<h3 id="3-원하는-함수에-openmodal-closemodal를-지정해준다">3. 원하는 함수에 openModal(), closeModal()를 지정해준다.</h3>
<p><img src="https://velog.velcdn.com/images/ttp_dev/post/2722997c-36ad-4602-9284-ff63ba718ae5/image.png" alt="">
<code>daum-postcode API</code>에서 주소가 <code>Input</code>에 들어오면 모달이 자동으로 닫히도록 설정했습니다.</p>
<p><img src="https://velog.velcdn.com/images/ttp_dev/post/f178e89b-a3c5-453f-beeb-679800a6c85e/image.png" alt="">
그리고 <code>도로명 주소 검색하기</code> 버튼을 누르면 모달이 열리도록 설정했습니다.</p>
<br>

<h3 id="4-마크업-가장-하단에-modalportal로-원하는-컴포넌트를-감싸준다">4. 마크업 가장 하단에 <code>&lt;ModalPortal&gt;</code>로 원하는 컴포넌트를 감싸준다</h3>
<p><img src="https://velog.velcdn.com/images/ttp_dev/post/b0f197f0-bcd8-43c5-b78c-21b88815d501/image.png" alt=""></p>
<br>

<h3 id="5-짠-react-portal을-사용한-모달-완성">5. 짠! react-portal을 사용한 모달 완성</h3>
<p><img src="https://velog.velcdn.com/images/ttp_dev/post/00b050f1-720e-4784-bdf3-bad91c52060e/image.png" alt=""></p>
<hr>
<h1 id="와-끝까지-읽어주셔서-감사합니다">와! 끝까지 읽어주셔서 감사합니다.</h1>
<p><img src="https://velog.velcdn.com/images/ttp_dev/post/115c773a-2db3-422e-9a4d-fa9cef6073ed/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NextJS에서 SVGR 적용하는 방법]]></title>
            <link>https://velog.io/@ttp_dev/NextJS%EC%97%90%EC%84%9C-SVGR-%EC%A0%81%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@ttp_dev/NextJS%EC%97%90%EC%84%9C-SVGR-%EC%A0%81%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Fri, 02 Feb 2024 05:32:16 GMT</pubDate>
            <description><![CDATA[<h2 id="1-svgrwebpack-설치하기">1. @svgr/webpack 설치하기</h2>
<pre><code class="language-bash">npm install @svgr/webpack --save-dev</code></pre>
<p>NextJS에서 SVGR을 사용하기 위해서는 웹펙과 관련된 설정을 추가해야한다. 그렇기 때문에 우선 <a href="https://www.npmjs.com/package/@svgr/webpack">@svgr/webpack</a>을 설치해준다.</p>
<h2 id="2-nextjs에-웹펙-설정-추가하기">2. NextJS에 웹펙 설정 추가하기</h2>
<pre><code class="language-javascript">/** @type {import(&#39;next&#39;).NextConfig} */
const nextConfig = {
  webpack: (config) =&gt; {
    config.module.rules.push({
      test: /\.svg$/,
      use: [&quot;@svgr/webpack&quot;],
    });
    return config;
  },
};

module.exports = nextConfig;
</code></pre>
<p>설치에 성공했다면 <code>next.config.js</code> 파일에 들어가 다음처럼 웹펙과 관련된 설정 코드를 추가해준다. svg 형식의 파일에는 <code>@svgr/webpack</code>을 적용해주겠다는 설정이다.</p>
<h2 id="3-svgr-사용하기">3. SVGR 사용하기</h2>
<p><img src="https://velog.velcdn.com/images/ttp_dev/post/791bd979-e355-483c-a67f-63f7b5424d0d/image.png" alt=""></p>
<p><code>/public</code>에 SVG 파일을 저장해둔 게 있다면, 이 파일을 이제 SVGR로 사용할 수 있다.</p>
<pre><code class="language-javascript">import AlertIcon from &quot;../../public/svg/alert-icon.svg&quot;;

export default function Home() {
  return &lt;AlertIcon /&gt;;
}
</code></pre>
<p><img src="https://velog.velcdn.com/images/ttp_dev/post/d5eea453-dda1-4d27-bc0e-4e97c2c1dd02/image.png" alt=""></p>
<pre><code class="language-javascript">import AlertIcon from &quot;../../public/svg/alert-icon.svg&quot;;

export default function Home() {
  return &lt;AlertIcon className=&quot;alert-icon&quot; /&gt;;
}
</code></pre>
<pre><code class="language-css">.alert-icon {
    /*스타일*/
}
</code></pre>
<p>SVG의 색상을 변경하고 싶다면 CSS 클래스를 추가해 수정할 수 있다.</p>
]]></description>
        </item>
    </channel>
</rss>