<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>zen_se.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Tue, 29 Aug 2023 11:20:58 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>zen_se.log</title>
            <url>https://images.velog.io/images/zen_se/profile/ccc7a6fa-ba1d-4ec2-96f2-dcd8b1b5ef48/social.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. zen_se.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/zen_se" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Routing - 라우트 가로채기]]></title>
            <link>https://velog.io/@zen_se/Routing-Intercepting-Routes</link>
            <guid>https://velog.io/@zen_se/Routing-Intercepting-Routes</guid>
            <pubDate>Tue, 29 Aug 2023 11:20:58 GMT</pubDate>
            <description><![CDATA[<h1 id="라우트-가로채기">라우트 가로채기</h1>
<p>라우트 가로채기를 통해 현재 레이아웃에서 애플리케이션의 다른 라우트를 로드할 수 있습니다. 이 라우트 패러다임은 사용자가 다른 컨텍스트로 변경하지 않고 다른 콘텐츠를 보여주고 싶을 때 유용합니다.</p>
<p>예를 들어, 피드에서 사진을 클릭하면 피드에 오버레이된 모달에서 사진이 표시됩니다. 이런 경우에 Next.js는 <code>/photo/123</code> 라우트를 가로채 URL를 마스크하고 <code>/feed</code>에 오버레이합니다.
<img src="https://velog.velcdn.com/images/zen_se/post/620b9fa9-8c20-46f2-9d48-e5d34f287d27/image.png" alt=""></p>
<p>그러나 공유 가능한 URL을 클릭하거나 페이지 새로고침으로 사진으로 이동하면 모달 대신 전체 사진 페이지가 렌더링되어야 합니다. 라우트 가로채기가 발생해서는 안 됩니다.
<img src="https://velog.velcdn.com/images/zen_se/post/e5c916fe-5aeb-47cd-b106-24f816dabafa/image.png" alt=""></p>
<h1 id="컨벤션">컨벤션</h1>
<p>경로 차단은 <code>(..)</code> 으로 정의할 수 있습니다. 이는 상대 경로 <code>../</code> 유사하지만 세그먼트에 대한 것입니다.</p>
<ul>
<li><code>(.)</code> 동일한 수준의 세그먼트와 일치</li>
<li><code>(..)</code> 한 수준 위의 세그먼트와 일치</li>
<li><code>(..)(..)</code> 두 수준 위의 세그먼트와 일치</li>
<li><code>(...)</code> 루트 앱 디렉터리의 세그먼트와 일치</li>
</ul>
<p>예를 들어, <code>(..)photo</code> 디렉토리를 생성하여 <code>feed</code> 세그먼트 내에서 <code>photo</code> 세그먼트를 가로챌 수 있습니다.
<img src="https://velog.velcdn.com/images/zen_se/post/475625cd-44c6-48cd-9842-8d802a2bd8ce/image.png" alt=""></p>
<blockquote>
<p>참고 : <code>(..)</code>는 파일 시스템이 아닌 라우트 세그먼트 기준으로 동작합니다.</p>
</blockquote>
<h1 id="example">Example</h1>
<h2 id="모달">모달</h2>
<p>라우트 가로채기는 병렬 라우트와 함께 사용하여 모달을 만들 수 있습니다.
이 패턴을 사용하여 모달을 생성하면 다음과 같은 기능을 통해 모달 작업 시 발생하는 몇 가지 일반적인 문제를 해결 할 수 있습니다.</p>
<ul>
<li>URL를 통해 공유 가능한 모달 콘텐츠 만들기</li>
<li>페이지 새로고침 시, 모달을 닫는 대신 컨텍스트 유지</li>
<li>이전페이지 기능으로 이전 라우트로 가는 대신 모달 닫기</li>
<li>다음페이지 기능으로 모달 다시 열기</li>
</ul>
<p><img src="https://velog.velcdn.com/images/zen_se/post/6c58d926-2c67-44e9-9705-d1412b729c64/image.png" alt=""></p>
<blockquote>
<ul>
<li>참고
위의 예에서 <code>@modal</code>은 세그먼트가 아니라 슬롯이므로 <code>photo</code> 세그먼트에 대한 라우트는 <code>(..)</code>를 사용할 수 있습니다. 이는 파일 시스템 수준이 두 개 더 높음에도 불구하고 <code>photo</code> 라우트가 한 세그먼트 수준만 높다는 것을 의미합니다.</li>
</ul>
</blockquote>
<p>다른 예시로는 전용 <code>/login</code> 페이지가 있는 동시에 상단 탐색 표시줄에서 로그인 모달을 열거나 측면 모달에서 장바구니를 여는 예시 등이 있습니다.</p>
<hr>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes">https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Routing - 병렬 라우팅]]></title>
            <link>https://velog.io/@zen_se/Routing-Parallel-Routes</link>
            <guid>https://velog.io/@zen_se/Routing-Parallel-Routes</guid>
            <pubDate>Thu, 24 Aug 2023 09:24:47 GMT</pubDate>
            <description><![CDATA[<h1 id="병렬-라우팅">병렬 라우팅</h1>
<p>병렬 라우팅을 사용하면 동일한 레이아웃에서 하나 이상의 페이지를 동시에 또는 조건부로 렌더링할 수 있습니다. 대시보드 및 소셜 사이트의 피드와 같이 매우 동적인 앱 섹션의 경우 병렬 라우팅을 사용하여 복잡한 라우팅 패턴을 구현할 수 있습니다.</p>
<p>예를 들어 팀 페이지와 분석 페이지를 동시에 렌더링할 수 있습니다.
<img src="https://velog.velcdn.com/images/zen_se/post/9c51b38c-1e67-4928-ad7d-a1a4bb3ffef2/image.png" alt=""></p>
<p>병렬 라우팅을 사용하면 라우트가 독립적으로 스트리밍될 때 각 라우트에 대해 독립적인 오류 및 로드 상태를 정의할 수 있습니다.
<img src="https://velog.velcdn.com/images/zen_se/post/7cd6a646-fc25-4282-bf4e-dd5977404337/image.png" alt=""></p>
<p>병렬 라우팅을 사용하면 인증 상태와 같은 특정 조건에 따라 슬롯을 조건부로 렌더링할 수도 있습니다. 이를 통해 동일한 URL에서 완전히 분리된 코드를 사용할 수 있습니다.
<img src="https://velog.velcdn.com/images/zen_se/post/83c0109a-25ec-4fca-b6f2-1c2e3981a3bd/image.png" alt=""></p>
<h1 id="컨벤션">컨벤션</h1>
<p>병렬 라우트는 슬롯을 사용하여 생성됩니다. 슬롯은 <code>@folder</code> 방식으로 정의되며 props와 동일한 수준 레이아웃에 전달됩니다.</p>
<blockquote>
<p>슬롯은 라우트 세그먼트가 아니며 URL 구조에 영향을 주지 않습니다. <code>/@team/members</code> 파일 경로는 <code>/members</code>로 액세스할 수 있습니다.</p>
</blockquote>
<p>예를 들어 다음 파일 구조는 <code>@analytics</code> 및 <code>@team</code>이라는 두 개의 명시적 슬롯을 정의합니다.
<img src="https://velog.velcdn.com/images/zen_se/post/0c077b26-a9b5-49f7-8a62-b4429c0067ba/image.png" alt=""></p>
<p>위의 폴더 구조는 <code>app/layout.js</code>의 컴포넌트가 이제 <code>@analytics</code> 및 <code>@team</code> 슬롯 props를 받아들이고 이를 children prop과 함께 병렬로 렌더링할 수 있음을 의미합니다.</p>
<pre><code class="language-jsx">/* app/layout.js */

export default function Layout(props) {
  return (
    &lt;&gt;
      {props.children}
      {props.team}
      {props.analytics}
    &lt;/&gt;
  )
}</code></pre>
<blockquote>
<p>참고 : children prop은 폴더에 매핑할 필요가 없는 암시적 슬롯입니다. 이는 <code>app/page.js</code>가 <code>app/@children/page.js</code>와 동일하다는 것을 의미합니다.</p>
</blockquote>
<h1 id="일치하지-않는-라우트">일치하지 않는 라우트</h1>
<p>기본적으로 슬롯 내에서 렌더링되는 콘텐츠는 현재 URL과 일치합니다.</p>
<p>URL이 일치하지 않는 슬롯의 경우 Next.js가 렌더링하는 콘텐츠는 라우팅 기술과 폴더 구조에 따라 다릅니다.</p>
<h2 id="defaultjs">default.js</h2>
<p>Next.js가 현재 URL을 기반으로 슬롯의 활성 상태를 복구할 수 없는 경우 대체 파일로 렌더링하도록 <code>default.js</code> 파일을 정의할 수 있습니다.</p>
<p>다음과 같은 폴더 구조에서 @team 슬롯에는 설정 디렉터리가 있지만 @analytics에는 없습니다.
<img src="https://velog.velcdn.com/images/zen_se/post/2ef26994-9197-4f1e-bb54-8f147ef1e464/image.png" alt=""></p>
<ul>
<li>navigation 시
navigation 시 Next.js는 현재 URL과 일치하지 않더라도 슬롯의 이전 활성 상태를 렌더링합니다.</li>
<li>reload 시
다시 로드할 때 Next.js는 먼저 일치하지 않는 슬롯의 <code>default.js</code> 파일을 렌더링하려고 시도합니다. 사용할 수 없는 경우 404가 렌더링됩니다.</li>
</ul>
<blockquote>
<p>일치하지 않는 경로에 대한 404는 병렬 렌더링되어서는 안 되는 경로를 실수로 렌더링하지 않도록 하는 데 도움이 됩니다.</p>
</blockquote>
<hr>
<h1 id="useselectedlayoutsegments">useSelectedLayoutSegment(s)</h1>
<p><code>useSelectedLayoutSegment</code> 와 <code>useSelectedLayoutSegments</code>는 <code>ParallelRoutesKey</code> 매개변수로 받아 해당 슬롯 내에서 활성 라우트 세그먼트를 읽을 수 있도록 합니다.</p>
<pre><code class="language-jsx">/* app/layout.js */

&#39;use client&#39;

import { useSelectedLayoutSegment } from &#39;next/navigation&#39;

export default async function Layout(props) {
  const loginSegments = useSelectedLayoutSegment(&#39;auth&#39;)
  // ...
}</code></pre>
<p>사용자가 <code>@auth/login</code> 또는 URL의 <code>/login</code>으로 이동하면 <code>loginSegments</code>는 &quot;login&quot; 문자열과 같습니다.</p>
<h1 id="example">Example</h1>
<h2 id="모달">모달</h2>
<p>병렬 라우팅은 모달을 렌더링하는데 사용될 수 있습니다.
<img src="https://velog.velcdn.com/images/zen_se/post/4cacf1cd-a59e-49f0-b43b-bb76b309be01/image.png" alt=""></p>
<p><code>@auth</code> 슬롯은 일치하는 라우트(예: /login)로 이동하여 표시할 수 있는 <code>&lt;Modal&gt;</code> 컴포넌트를 렌더링합니다.</p>
<pre><code class="language-jsx">/* app/layout.js */

export default async function Layout(props) {
  return (
    &lt;&gt;
      {/* ... */}
      {props.auth}
    &lt;/&gt;
  )
}</code></pre>
<pre><code class="language-jsx">/* app/@auth/login/page.js */

import { Modal } from &#39;components/modal&#39;

export default function Login() {
  return (
    &lt;Modal&gt;
      &lt;h1&gt;Login&lt;/h1&gt;
      {/* ... */}
    &lt;/Modal&gt;
  )
}</code></pre>
<p>모달이 활성화되지 않은 경우 모달의 콘텐츠가 렌더링되지 않도록 하려면 null을 반환하는 <code>default.js</code> 파일을 생성하면 됩니다.</p>
<pre><code class="language-jsx">/* app/@auth/default.js */

export default function Default() {
  return null
}</code></pre>
<h3 id="모달-지우기">모달 지우기</h3>
<p>클라이언트 탐색을 통해 모달이 시작된 경우(예: <code>&lt;Link href=&quot;/login&quot;&gt;</code>) , <code>router.back()</code>을 호출하거나 <code>Link</code> 컴포넌트를 사용하여 모달을 해제할 수 있습니다.</p>
<pre><code class="language-jsx">/* app/@auth/login/page.js */

&#39;use client&#39;
import { useRouter } from &#39;next/navigation&#39;
import { Modal } from &#39;components/modal&#39;

export default async function Login() {
  const router = useRouter()
  return (
    &lt;Modal&gt;
      &lt;span onClick={() =&gt; router.back()}&gt;Close modal&lt;/span&gt;
      &lt;h1&gt;Login&lt;/h1&gt;
      ...
    &lt;/Modal&gt;
  )
}</code></pre>
<blockquote>
<p>모달에 대한 자세한 내용은 Intercepting Routes 섹션에서 다룹니다.</p>
</blockquote>
<p>다른 곳으로 이동하고 모달을 닫으려면 catch-all 라우트를 사용할 수도 있습니다.
<img src="https://velog.velcdn.com/images/zen_se/post/55b8634d-efa5-4e55-b67f-88f9abdd25ac/image.png" alt=""></p>
<pre><code class="language-jsx">/* app/@auth/[...catchAll]/page.js */

export default function CatchAll() {
  return null
}</code></pre>
<blockquote>
<p>catch-all 라우트는 <code>default.js</code>보다 우선됩니다.</p>
</blockquote>
<h1 id="조건부-라우트">조건부 라우트</h1>
<p>병렬 경로를 사용하여 조건부 라우팅을 구현할 수 있습니다. 예를 들어 인증 상태에 따라 <code>@dashboard</code> 또는 <code>@login</code> 라우트를 렌더링할 수 있습니다.</p>
<pre><code class="language-jsx">/* app/layout.js */

import { getUser } from &#39;@/lib/auth&#39;

export default function Layout({ dashboard, login }) {
  const isLoggedIn = getUser()
  return isLoggedIn ? dashboard : login
}</code></pre>
<p><img src="https://velog.velcdn.com/images/zen_se/post/c2f6cc8b-5803-480e-b6f6-2d9a80068378/image.png" alt=""></p>
<hr>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs/app/building-your-application/routing/parallel-routes">https://nextjs.org/docs/app/building-your-application/routing/parallel-routes</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Routing - 에러 핸들링]]></title>
            <link>https://velog.io/@zen_se/Routing-Error-Handling</link>
            <guid>https://velog.io/@zen_se/Routing-Error-Handling</guid>
            <pubDate>Thu, 24 Aug 2023 08:22:22 GMT</pubDate>
            <description><![CDATA[<h1 id="에러-핸들링">에러 핸들링</h1>
<p><code>error.js</code> 파일을 사용하면 중첩된 라우트에서 예기치 않은 런타임 오류를 적절하게 처리할 수 있습니다.</p>
<ul>
<li><p>React Error Boundary에서 라우트 세그먼트와 중첩된 하위 항목을 자동으로 래핑합니다.</p>
</li>
<li><p>파일 시스템 계층을 사용하여 특정 세그먼트에 맞게 조정된 오류 UI 생성합니다.</p>
</li>
<li><p>나머지 애플리케이션 기능을 유지하면서 영향을 받는 세그먼트에 오류를 격리합니다.</p>
</li>
<li><p>전체 페이지를 다시 로드하지 않고 오류 복구를 시도하는 기능을 추가합니다.</p>
</li>
</ul>
<p>라우트 세그먼트 내에 <code>error.js</code> 파일을 추가하고 React 컴포넌트를 export해 오류 UI를 만듭니다.</p>
<p><img src="https://velog.velcdn.com/images/zen_se/post/bb6e2416-0045-464b-b9ad-d3db5c3dcdc8/image.png" alt=""></p>
<pre><code class="language-jsx">/* app/dashboard/error.js */

&#39;use client&#39; // Error components must be Client Components

import { useEffect } from &#39;react&#39;

export default function Error({ error, reset }) {
  useEffect(() =&gt; {
    // Log the error to an error reporting service
    console.error(error)
  }, [error])

  return (
    &lt;div&gt;
      &lt;h2&gt;Something went wrong!&lt;/h2&gt;
      &lt;button
        onClick={
          // Attempt to recover by trying to re-render the segment
          () =&gt; reset()
        }
      &gt;
        Try again
      &lt;/button&gt;
    &lt;/div&gt;
  )
}</code></pre>
<hr>
<h1 id="errorjs-작동-방식">error.js 작동 방식</h1>
<p><img src="https://velog.velcdn.com/images/zen_se/post/131d8385-05ed-4fa7-9c8c-57565d283604/image.png" alt=""></p>
<ul>
<li><code>error.js</code>는 자동으로 중첩된 하위 세그먼트와 <code>page.js</code>를 감싸는 <code>React Error Boundary</code>를 생성합니다.</li>
<li><code>error.js</code> 파일에서 export 된 컴포넌트가 fallback 컴포넌트로 사용됩니다.</li>
<li>Error Boundary 안에서 에러가 발생하면 에러가 발생한 채로 fallback 컴포넌트가 렌더링됩니다.</li>
<li>fallback 컴포넌트가 활성화되면 Error Boundary 상위의 레이아웃은 state와 상호작용을 유지하며 오류 컴포넌트는 오류를 복구하는 기능을 표시할 수 있습니다.</li>
</ul>
<h1 id="오류-복구하기">오류 복구하기</h1>
<p>오류의 원인이 일시적일 수 있습니다. 이러한 경우 다시 시도하면 문제가 해결될 수도 있습니다.
오류 컴포넌트는 <code>reset()</code> 함수를 사용하여 사용자에게 오류 복구를 시도하라는 메시지를 표시할 수 있습니다. <code>reset()</code>이 실행되면 함수는 Error Boundary의 내용을 다시 렌더링하려고 시도합니다. 성공하면 fallback 컴포넌트가 다시 렌더링된 결과로 대체됩니다.</p>
<h1 id="중첩-라우트">중첩 라우트</h1>
<p>특수 파일을 통해 생성된 React 컴포넌트는 특정 중첩 계층 구조로 렌더링됩니다.</p>
<p>예를 들어, <code>layout.js</code> 및 <code>error.js</code> 파일을 모두 포함하는 두 개의 세그먼트가 있는 중첩 라우트는 다음과 같은 단순화된 컴포넌트 계층 구조로 렌더링됩니다.
<img src="https://velog.velcdn.com/images/zen_se/post/b599e52f-52a2-4800-93fa-3c21f84703b8/image.png" alt=""></p>
<p>중첩된 컴포넌트 계층 구조는 중첩된 경로에서 <code>error.js</code> 파일의 동작에 영향을 미칩니다.</p>
<ul>
<li>오류는 가장 가까운 상위 Error Boundary까지 표시됩니다. 이는 <code>error.js</code> 파일이 중첩된 모든 하위 세그먼트에 대한 오류를 처리한다는 의미입니다. 라우트의 중첩 폴더에서 서로 다른 수준에 <code>error.js</code> 파일을 배치하면 세분화된 오류 UI를 얻을 수 있습니다.</li>
<li>Error Boundary는 같은 세그먼트의 Layout 컴포넌트 내에 중첩되어 있으므로 <code>error.js</code>는 동일한 세그먼트의 <code>layout.js</code> 컴포넌트에서 발생한 오류를 처리하지 않습니다.</li>
</ul>
<h1 id="layout의-에러-처리하기">Layout의 에러 처리하기</h1>
<p><code>error.js</code>는 동일한 세그먼트의 <code>layout.js</code> 또는 <code>template.js</code> 컴포넌트에서 발생하는 오류를 감지하지 않습니다. 이 의도적인 계층 구조는 오류가 발생할 때 형제 라우트 간에 공유되는 중요한 UI를 표시하고 작동하도록 유지합니다. ex) 네비게이션 바</p>
<p>특정 레이아웃이나 템플릿 내의 오류를 처리하려면 <code>error.js</code> 파일을 레이아웃의 상위 세그먼트에 배치하세요.</p>
<p>루트 레이아웃이나 루트 템플릿 내의 오류를 처리하려면 <code>error.js</code>의 변형인 <code>global-error.js</code>을 사용하세요.</p>
<h1 id="root-layout의-에러-처리하기">Root Layout의 에러 처리하기</h1>
<p>루트 <code>app/error.js</code>의 범위는 루트 <code>app/layout.js</code> 또는 <code>app/template.js</code> 컴포넌트에서 발생한 오류를 감지하지 않습니다.</p>
<p>이러한 루트 컴포넌트의 오류를 처리하려면 루트 app 디렉토리에 있는 <code>app/global-error.js</code>라는 <code>error.js</code> 변형을 사용하세요.</p>
<p>루트 <code>error.js</code>와 달리 <code>global-error.js</code>의 Error Boundary는 전체 애플리케이션을 감싸고 해당 fallback 컴포넌트는 활성화되면 루트 레이아웃을 대체합니다.    이 때문에 <code>global-error.js</code>에 자체적인 <code>&lt;html&gt;</code> 과 <code>&lt;body&gt;</code>태그가 정의되어야 한다는 점을 유의해야합니다.</p>
<p><code>global-error.js</code>는 가장 세분화되지 않은 오류 UI이며 전체 애플리케이션에 대한 포괄적인 오류 처리로 간주될 수 있습니다. 루트 컴포넌트는 일반적으로 동적인 경우가 적으며 다른 <code>error.js</code> Boundary는 대부분의 오류를 포착하므로 <code>global-error.js</code>가 자주 트리거될 가능성이 없습니다.</p>
<p><code>global-error.js</code>가 정의된 경우에도 전역으로 공유되는 UI 및 브랜딩을 포함하는 루트 레이아웃 내에서 fallback 컴포넌트가 렌더링될 루트 <code>error.js</code>를 정의하는 것이 좋습니다.</p>
<pre><code class="language-jsx">/* app/global-error.js */

&#39;use client&#39;

export default function GlobalError({ error, reset }) {
  return (
    &lt;html&gt;
      &lt;body&gt;
        &lt;h2&gt;Something went wrong!&lt;/h2&gt;
        &lt;button onClick={() =&gt; reset()}&gt;Try again&lt;/button&gt;
      &lt;/body&gt;
    &lt;/html&gt;
  )
}</code></pre>
<h1 id="서버-에러-처리하기">서버 에러 처리하기</h1>
<p>서버 컴포넌트 내부에서 오류가 발생하면 Next.js는 error 객체(프로덕션에서 민감한 오류 정보가 제거된)를 가장 가까운 <code>error.js</code> 파일에 error prop으로 전달합니다.</p>
<h2 id="민감한-오류-정보-보호">민감한 오류 정보 보호</h2>
<p>프로덕션 환경에서 클라이언트에 전달되는 Error 객체에는 일반 <code>message</code>와 <code>digest</code> 프로퍼티만 포함됩니다.</p>
<p>이는 오류에 포함된 잠재적으로 민감한 세부 정보가 클라이언트에 유출되는 것을 방지하기 위한 보안 예방 조치입니다.</p>
<p><code>message</code> 프로퍼티에는 오류에 대한 일반 메시지가 포함되어 있으며 <code>digest</code> 프로퍼티에는 서버 측 로그의 해당 오류와 일치시키는 데 사용할 수 있는 자동으로 생성된 오류 해시가 포함되어 있습니다.</p>
<p>개발 환경에서 클라이언트에 전달된 Error 개체는 직렬화되고 보다 쉬운 디버깅을 위해 원래 오류 메시지를 포함합니다.</p>
<hr>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs/app/building-your-application/routing/error-handling">https://nextjs.org/docs/app/building-your-application/routing/error-handling</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Routing - 로딩 UI와 Streaming]]></title>
            <link>https://velog.io/@zen_se/Routing-LoadingUI-and-Streaming</link>
            <guid>https://velog.io/@zen_se/Routing-LoadingUI-and-Streaming</guid>
            <pubDate>Sat, 19 Aug 2023 11:15:16 GMT</pubDate>
            <description><![CDATA[<h1 id="로딩-ui와-streaming">로딩 UI와 Streaming</h1>
<p>특별한 파일인 <code>loading.js</code>가 <code>React Suspense</code>와 함께 의미있는 로딩 UI를 만들 수 있도록 도와줍니다. 이 방식을 사용하면 라우트 세그먼트의 콘텐츠가 로드되는 동안 서버로부터 일시적인 로드 상태(instant loading state)를 보여줄 수 있습니다. 해당 콘텐츠의 렌더링이 끝나면 새 콘텐츠는 자동으로 교체됩니다.
<img src="https://velog.velcdn.com/images/zen_se/post/d1e2ea03-6866-4f84-aa5e-f84ea0d022e0/image.png" alt=""></p>
<ul>
<li><a href="https://www.daleseo.com/react-suspense/">React Suspense 소개</a></li>
</ul>
<h1 id="일시적인-로드-상태">일시적인 로드 상태</h1>
<p>일시적인 로드 상태(instant loading state)는 페이지 탐색 시 즉시 표시되는 대체 UI입니다. 스켈레톤 및 스피너와 같은 로딩 표시기 또는 표지 사진, 제목 등과 같이 이후 화면의 작지만 의미 있는 부분을 미리 렌더링할 수 있습니다. 이를 통해 사용자는 애플리케이션이 응답하고 있음을 이해하고 더 나은 사용자 경험을 제공할 수 있습니다.</p>
<p>폴더 안에 <code>loading.js</code> 파일을 추가하여 로딩 상태를 만듭니다.
<img src="https://velog.velcdn.com/images/zen_se/post/e0c50cff-c805-4441-90c0-141a0d0cfe44/image.png" alt=""></p>
<pre><code class="language-jsx">/* app/dashboard/loading.js */

export default function Loading() {
  // You can add any UI inside Loading, including a Skeleton.
  return &lt;LoadingSkeleton /&gt;
}</code></pre>
<hr>
<p>같은 폴더에서 <code>loading.js</code>는 <code>layout.js</code> 내부에 들어가게됩니다. 그리고 <code>loading.js</code>는 Suspense 경계에서 <code>page.js</code> 파일과 그 아래의 모든 자식을 자동으로 감쌉니다.
<img src="https://velog.velcdn.com/images/zen_se/post/44153eb4-73dc-489b-8428-d568b8e4b9cd/image.png" alt=""></p>
<hr>
<h1 id="suspense로-streaming">Suspense로 Streaming</h1>
<p>loading.js 외에도 자체 UI 컴포넌트에 대한 Suspense 경계를 직접 생성할 수도 있습니다. app 라우터는 Node.js 및 Edge 런타임 모두에 대해 Suspense를 사용한 <code>Streaming</code>을 지원합니다.</p>
<h2 id="streaming이란">Streaming이란?</h2>
<p>React와 Next.js에서 Streaming이 작동하는 방식을 알아보려면 <code>SSR(Server-Side Rendering)</code>과 그 한계점을 이해하는 것이 좋습니다.</p>
<p>SSR에서 사용자가 페이지를 보고 상호 작용하기 전에 완료해야 하는 일련의 단계가 있습니다.</p>
<ol>
<li>주어진 페이지의 모든 데이터를 서버에서 가져옵니다.</li>
<li>서버는 페이지의 HTML을 렌더링합니다.</li>
<li>페이지의 HTML, CSS 및 JavaScript가 클라이언트로 전송됩니다.</li>
<li>비대화형 UI는 생성된 HTML 및 CSS를 사용하여 표시됩니다.</li>
<li>React는 UI를 <code>hydrate</code>(수화)시켜 대화형으로 만듭니다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/zen_se/post/548acaa7-fc86-449f-a6f6-a98caa210f69/image.png" alt=""></p>
<p>이러한 단계는 순차적입니다. 즉, 모든 데이터를 가져온 후에만 서버가 페이지의 HTML을 렌더링할 수 있습니다. 그리고 클라이언트에서 React는 페이지의 모든 구성 요소에 대한 코드가 다운로드된 후에만 UI를 <code>hydrate</code>할 수 있습니다.</p>
<p>React와 Next.js를 사용하는 SSR은 가능한 한 빨리 사용자에게 비대화형 페이지를 표시하여 체감되는 로딩 성능을 개선하는데 도움을 줍니다.</p>
<p><img src="https://velog.velcdn.com/images/zen_se/post/a951a8bf-155e-4542-aa56-46949abba6d7/image.png" alt="">
그러나 페이지가 사용자에게 표시되기 전에 서버에서 모든 데이터 fetch를 완료해야 하므로 속도가 여전히 느릴 수 있습니다.</p>
<p><code>Streaming</code>을 사용하면 페이지의 HTML을 더 작은 청크로 분해하고 해당 청크를 서버에서 클라이언트로 점진적으로 보낼 수 있습니다.
<img src="https://velog.velcdn.com/images/zen_se/post/19052fb7-6b95-45d3-bcc2-40036a1e415d/image.png" alt="">
이렇게 하면 UI가 렌더링되기 전에 모든 데이터가 로드될 때까지 기다리지 않고 페이지의 일부를 더 빨리 표시할 수 있습니다.</p>
<p><code>Streaming</code>은 각 컴포넌트를 청크로 생각할 수 있는 React의 컴포넌트 모델에서 잘 작동합니다. 우선 순위가 더 높거나(예: 제품 정보) 데이터에 의존하지 않는 컴포넌트(예: 레이아웃)를 먼저 보낼 수 있으며 React는 더 일찍 수화를 시작할 수 있습니다. 우선 순위가 낮은 컴포넌트(예: 리뷰, 관련 제품)는 데이터 fetch가 끝난 뒤 동일한 서버 요청으로 보낼 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/zen_se/post/ef363594-cda7-411a-928d-04d638f21248/image.png" alt=""></p>
<p>스트리밍은 <code>TTFB(Time To First Byte)</code> 및 <code>FCP(First Contentful Paint)</code>를 줄일 수 있으므로 긴 데이터 요청으로 인해 페이지 렌더링이 차단되지 않도록 하려는 경우에 특히 유용합니다. 또한 특히 느린 장치에서 <code>TTI(Time to Interactive)</code>를 개선하는 데 도움이 됩니다.</p>
<h2 id="예시">예시</h2>
<p><code>&lt;Suspense&gt;</code>는 비동기 작업(예: 데이터 가져오기)을 수행하는 컴포넌트를 래핑하고 작업이 진행되는 동안 fallback(대체) UI(예: 스켈레톤, 스피너)를 표시한 다음 작업이 완료되면 컴포넌트를 교체하는 방식으로 작동합니다.</p>
<pre><code class="language-jsx">/* app/dashboard/page.js */

import { Suspense } from &#39;react&#39;
import { PostFeed, Weather } from &#39;./Components&#39;

export default function Posts() {
  return (
    &lt;section&gt;
      &lt;Suspense fallback={&lt;p&gt;Loading feed...&lt;/p&gt;}&gt;
        &lt;PostFeed /&gt;
      &lt;/Suspense&gt;
      &lt;Suspense fallback={&lt;p&gt;Loading weather...&lt;/p&gt;}&gt;
        &lt;Weather /&gt;
      &lt;/Suspense&gt;
    &lt;/section&gt;
  )
}</code></pre>
<p><code>Suspense</code>를 사용하면 다음과 같은 이점을 얻을 수 있습니다.</p>
<ol>
<li><code>Streaming 서버 렌더링</code>
서버에서 클라이언트로 HTML을 점진적으로 렌더링합니다.</li>
<li><code>선택적 수화</code>
React는 사용자 상호 작용을 기반으로 먼저 수화시킬 컴포넌트 우선 순위를 지정합니다.</li>
</ol>
<ul>
<li><a href="https://react-ko.dev/reference/react/Suspense">React Suspense 공식문서 한글번역</a></li>
</ul>
<hr>
<h2 id="seo-검색-엔진-최적화">SEO (검색 엔진 최적화)</h2>
<p>Next.js는 UI를 클라이언트로 Streaming하기 전에 <code>generateMetadata</code> 내에서 데이터 fetch가 완료될 때까지 기다립니다. 이는 Streaming 응답의 첫 번째 부분에 <code>&lt;head&gt;</code> 태그가 포함되는 것이 보장됩니다.</p>
<p>Streaming은 서버 렌더링이므로 SEO에 영향을 미치지 않습니다. Google의 모바일 친화성 테스트 도구를 사용하여 페이지가 Google 웹 크롤러에 어떻게 표시되는지 확인하고 직렬화된 HTML을 볼 수 있습니다.</p>
<hr>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming">https://nextjs.org/docs/app/building-your-application/routing/loading-ui-and-streaming</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Routing - 동적 라우트]]></title>
            <link>https://velog.io/@zen_se/Routing-Dynamic-Routes</link>
            <guid>https://velog.io/@zen_se/Routing-Dynamic-Routes</guid>
            <pubDate>Fri, 18 Aug 2023 10:42:55 GMT</pubDate>
            <description><![CDATA[<h1 id="동적-라우트">동적 라우트</h1>
<p>정확한 세그먼트 이름을 미리 알지 못하고 동적 데이터에서 라우트를 생성하려는 경우 요청 시 채워지거나 빌드 시 미리 렌더링되는 동적 세그먼트를 사용할 수 있습니다.</p>
<h1 id="컨벤션">컨벤션</h1>
<p>동적 세그먼트는 폴더 이름을 대괄호로 묶음으로써 생성할 수 있습니다.
ex) <code>[folderName]</code>, <code>[id]</code>, <code>[slug]</code></p>
<h1 id="example">Example</h1>
<p>예를 들어 블로그에는 <code>app/blog/[slug]/page.js</code> 라우트가 있을 수 있습니다. 여기서 <code>[slug]</code>는 블로그 게시물의 동적 세그먼트입니다.</p>
<pre><code class="language-jsx">/* app/blog/[slug]/page.js */

export default function Page({ params }) {
  return &lt;div&gt;My Post: {params.slug}&lt;/div&gt;
}</code></pre>
<p>전달받는 <code>params</code>에 따라 URL이 바뀝니다.
<code>params = { slug : &#39;a&#39; }</code> --&gt; <code>URL : /blog/a</code>
<code>params = { slug : &#39;b&#39; }</code> --&gt; <code>URL : /blog/b</code></p>
<p>세그먼트에 대한 매개변수를 생성하는 방법은 이후 <code>generateStaticParams()</code>에서 알아보겠습니다.</p>
<h1 id="정적-매개변수-생성generatestaticparams">정적 매개변수 생성(generateStaticParams)</h1>
<p><code>generateStaticParams</code> 함수는 동적 라우트 세그먼트와 함께 사용되어 빌드 타임에 라우트를 정적으로 생성할 수 있습니다.</p>
<pre><code class="language-jsx">/* app/blog/[slug]/page.js */

export async function generateStaticParams() {
  const posts = await fetch(&#39;https://.../posts&#39;).then((res) =&gt; res.json())

  return posts.map((post) =&gt; ({
    slug: post.slug,
  }))
}</code></pre>
<p><code>generateStaticParams</code> 함수의 이점은 함수 내에서 <code>fetch</code> 요청을 사용하여 콘텐츠를 가져오면 해당 요청이 자동으로 메모되는 것 입니다. 이는 여러 <code>generateStaticParams</code>, 레이아웃, 페이지에서 동일한 인수를 사용하는 <code>fetch</code> 요청이 한 번만 이루어지므로 빌드 시간이 단축됨을 의미합니다.</p>
<ul>
<li><a href="https://nextjs.org/docs/app/api-reference/functions/generate-static-params"><code>generateStaticParams</code> docs</a> 참고</li>
</ul>
<h1 id="catch-all-세그먼트">Catch-all 세그먼트</h1>
<p>동적 세그먼트는 폴더 이름 앞에 <code>...</code>을 추가해서 <code>catch-all(광범위)</code> 세그먼트로 확장될 수 있습니다. ex) <code>[...foldername]</code></p>
<p>예를 들어, <code>app/shop/[...slug]/page.js</code>는 <code>/shop/clothes</code>에 매치될뿐만 아니라 <code>/shop/clothes/tops</code>, <code>/shop/clothes/tops/t-shirts</code>에도 매치됩니다.</p>
<p>ex) 라우트 : <code>app/shop/[...slug]/page.js</code></p>
<table>
<thead>
<tr>
<th align="center">URL</th>
<th align="center"><code>params</code></th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>/shop/a</code></td>
<td align="center"><code>{ slug: [&#39;a&#39;] }</code></td>
</tr>
<tr>
<td align="center"><code>/shop/a/b</code></td>
<td align="center"><code>{ slug: [&#39;a&#39;, &#39;b&#39;] }</code></td>
</tr>
<tr>
<td align="center"><code>/shop/a/b/c</code></td>
<td align="center"><code>{ slug: [&#39;a&#39;, &#39;b&#39;, &#39;c&#39;] }</code></td>
</tr>
</tbody></table>
<h1 id="선택적-catch-all-세그먼트">선택적 Catch-all 세그먼트</h1>
<p>폴더 이름에 이중 대괄호를 사용하여 Catch-all 세그먼트를 선택적 Catch-all 세그먼트로 만들 수 있습니다. ex) <code>[[...foldername]]</code></p>
<p>Catch-all 세그먼트와의 차이점은 선택적 Catch-all 세그먼트는 매개변수가 없어도 매치된다는 점 입니다.</p>
<p>ex) 라우트 : <code>app/shop/[[...slug]]/page.js</code></p>
<table>
<thead>
<tr>
<th align="center">URL</th>
<th align="center"><code>params</code></th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>/shop</code></td>
<td align="center"><code>{}</code></td>
</tr>
<tr>
<td align="center">나머진 Catch-all과 동일</td>
<td align="center"></td>
</tr>
</tbody></table>
<h1 id="typescript-사용시">TypeScript 사용시</h1>
<p>TypeScript를 사용할 때 라우트 세그먼트에 따라 매개변수 타입을 추가할 수 있습니다.</p>
<pre><code class="language-tsx">export default function Page({ params }: { params: { slug: string } }) {
  return &lt;h1&gt;My Page&lt;/h1&gt;
}</code></pre>
<table>
<thead>
<tr>
<th align="center">Route</th>
<th align="center">params 타입 정의</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>app/blog/[slug]/page.js</code></td>
<td align="center"><code>{ slug: string }</code></td>
</tr>
<tr>
<td align="center"><code>app/shop/[...slug]/page.js</code></td>
<td align="center"><code>{ slug: string[] }</code></td>
</tr>
<tr>
<td align="center"><code>app/[categoryId]/[itemId]/page.js</code></td>
<td align="center"><code>{ categoryId: string, itemId: string }</code></td>
</tr>
</tbody></table>
<hr>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes">https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Routing - 라우트 그룹]]></title>
            <link>https://velog.io/@zen_se/Routing-Route-Groups</link>
            <guid>https://velog.io/@zen_se/Routing-Route-Groups</guid>
            <pubDate>Fri, 18 Aug 2023 09:33:19 GMT</pubDate>
            <description><![CDATA[<h1 id="라우트-그룹">라우트 그룹</h1>
<p>일반적으로 <code>app</code> 디렉토리에서 중첩된 폴더는 URL path에 매핑됩니다. 그러나 폴더를 <code>라우트 그룹</code>으로 설정하면 폴더가 URL path에 포함되지 않게 할 수 있습니다.</p>
<p>이렇게 하면 URL path 구조에 영향을 주지 않고 라우트 세그먼트와 프로젝트 파일을 논리적 그룹으로 구분할 수 있습니다.</p>
<p>라우트 그룹은 다음같은 경우에 유용합니다 :</p>
<ul>
<li>그룹별로 라우트를 구성 ex) 사이트 섹션, 기능, 팀 별</li>
<li>동일한 라우트 세그먼트 수준에서 중첩된 레이아웃 가능<ul>
<li>동일한 세그먼트에 여러 중첩 레이아웃 생성 ex) 복수의 루트 레이아웃 생성</li>
<li>공통 세그먼트의 라우트 부분 집합에 레이아웃 추가</li>
</ul>
</li>
</ul>
<h1 id="컨벤션">컨벤션</h1>
<p>폴더의 이름을 <code>( )</code>로 감싸면 라우트 그룹을 생성할 수 있습니다.
ex) <code>(foldername)</code></p>
<h1 id="example">Example</h1>
<h2 id="1-url-path에-영향을-주지-않고-라우트-그룹화">1. URL path에 영향을 주지 않고 라우트 그룹화</h2>
<p>URL에 영향을 주지 않고 관련 라우트를 그룹화하기 위해 라우트 그룹을 생성합니다. 괄호안의 폴더는 URL에서 생략됩니다.</p>
<p>다음 그림에서 <code>(marketing)</code>, <code>(shop)</code>은 URL에 포함되지 않습니다.
<img src="https://velog.velcdn.com/images/zen_se/post/d1793631-7e43-49f7-9b35-9fa8018bf6c2/image.png" alt=""></p>
<p><code>(marketing)</code>과 <code>(shop)</code> 내부의 경로가 동일한 URL 계층 구조를 공유하더라도 폴더 내에 <code>layout.js</code> 파일을 추가하여 각 그룹에 대해 다른 레이아웃을 생성할 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/zen_se/post/86ce5123-6d8c-43e3-8ce4-c362b96063ff/image.png" alt=""></p>
<h2 id="2-특정-세그먼트에만-레이아웃-적용">2. 특정 세그먼트에만 레이아웃 적용</h2>
<p>특정 세그먼트에만 레이아웃을 적용하기 위해서 새로운 라우트 그룹 <code>(shop)</code>을 생성하고, 동일한 레이아웃을 공유할 <code>account</code>와 <code>cart</code>를 그룹안으로 이동합니다. 그룹 밖의 라우트인 <code>checkout</code>은 레이아웃을 공유하지 않습니다.</p>
<p><img src="https://velog.velcdn.com/images/zen_se/post/0e56afd2-311b-4580-ba6b-a47d19cf7387/image.png" alt=""></p>
<h2 id="3-복수의-루트-레이아웃-생성">3. 복수의 루트 레이아웃 생성</h2>
<p>복수의 루트 레이아웃을 생성하기 위해서 최상단의 <code>layout.js</code>파일을 제거하고, 각 라우트 그룹에 <code>layout.js</code>파일을 추가합니다. 이것은 완전히 다른 UI/UX를 가진 섹션으로 애플리케이션을 분할하는 데 유용합니다.
<code>&lt;html&gt;</code>과 <code>&lt;body&gt;</code>태그는 각 루트 레이아웃마다 추가되어야합니다.
<img src="https://velog.velcdn.com/images/zen_se/post/5d7a11a0-cb05-4ec1-b4b8-19d91cd3eeaf/image.png" alt="">
위 그림에서 <code>(marketing)</code>과 <code>(shop)</code>은 각자 고유한 루트 레이아웃을 가집니다.</p>
<blockquote>
<p>참고 :</p>
</blockquote>
<ul>
<li>라우트 그룹의 이름은 그룹화 이외의 특별한 의미는 없습니다. URL path에 영향을 주지 않습니다.</li>
<li>라우트 그룹을 포함한 라우트의 URL의 중복이 존재하면 안됩니다. 예를 들어 <code>(marketing)/about/page.js</code>과 <code>(shop)/about/page.js</code>는 모두 <code>/about</code>으로 인식되고 에러를 발생시킵니다.</li>
<li>만약 최상단의 루트 레이아웃 없이 복수 루트 레이아웃을 사용할 경우, home(<code>/</code>에 해당하는 <code>page.js</code>)은 라우트 그룹 중 하나에만 존재해야합니다. ex) <code>app/(marketing)/page.js</code></li>
<li>복수 루트 레이아웃에서 루트 레이아웃 간에 이동은 전체 페이지 로드를 발생시킵니다. 이것은 복수 루트 레이아웃을 사용할 때만 적용됩니다.
ex) <code>app/(shop)/layout.js</code>를 사용하는 <code>/cart</code>에서 <code>app/(marketing)/layout.js</code>를 사용하는 <code>/blog</code>로 이동 시</li>
</ul>
<hr>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs/app/building-your-application/routing/route-groups">https://nextjs.org/docs/app/building-your-application/routing/route-groups</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Routing - Linking과 Navigating]]></title>
            <link>https://velog.io/@zen_se/Routing-Linking-and-Navigating</link>
            <guid>https://velog.io/@zen_se/Routing-Linking-and-Navigating</guid>
            <pubDate>Tue, 15 Aug 2023 11:00:16 GMT</pubDate>
            <description><![CDATA[<h1 id="linking과-navigating">Linking과 Navigating</h1>
<p>Next.js에는 라우트 사이를 이동하는 두가지 방법이 있습니다</p>
<ul>
<li><code>&lt;Link&gt;</code> 컴포넌트 사용</li>
<li><code>useRouter</code> Hook 사용</li>
</ul>
<h1 id="link-컴포넌트"><code>&lt;Link&gt;</code> 컴포넌트</h1>
<ul>
<li>HTML의 <code>&lt;a&gt;</code> 태그를 확장한 내장 컴포넌트</li>
<li><code>prefetching</code>과 <code>client-side navigation</code> 제공<ul>
<li><code>prefetching</code> : Link 컴포넌트가 브라우저의 viewport에 나타나면 Next.js가 백그라운드에서 링크된 페이지의 코드를 자동으로 미리 가져옴</li>
<li><code>client-side navigation</code> : 전체 페이지를 로드하는 것이 아닌 js로 페이지 전환</li>
</ul>
</li>
</ul>
<p><code>next/link</code>를 import 해야 사용이 가능하고, herf 속성을 넘겨줍니다.</p>
<pre><code class="language-jsx">import Link from &#39;next/link&#39;

export default function Page() {
  return &lt;Link href=&quot;/dashboard&quot;&gt;Dashboard&lt;/Link&gt;
}</code></pre>
<p>herf 이외에도 다른 속성을 지정할 수 있습니다. - <a href="https://nextjs.org/docs/app/api-reference/components/link">Link API</a></p>
<h2 id="link-예제"><code>&lt;Link&gt;</code> 예제</h2>
<h3 id="1-다이나믹-세그먼트-link">1. 다이나믹 세그먼트 Link</h3>
<p>(Dynamic Route 문서 참고)</p>
<p>다이나믹 세그먼트를 Link하려면 템플릿 리터럴(` `)과 인터폴레이션(${ })을 사용합니다.</p>
<p>다음은 블로그 게시글 리스트를 생성하는 예제입니다.</p>
<pre><code class="language-jsx">import Link from &#39;next/link&#39;

export default function PostList({ posts }) {
  return (
    &lt;ul&gt;
      {posts.map((post) =&gt; (
        &lt;li key={post.id}&gt;
          &lt;Link href={`/blog/${post.slug}`}&gt;{post.title}&lt;/Link&gt;
        &lt;/li&gt;
      ))}
    &lt;/ul&gt;
  )
}</code></pre>
<h3 id="2-현재-활성화된-링크-확인">2. 현재 활성화된 링크 확인</h3>
<p><code>usePathname()</code>을 사용하여 현재 <code>pathname</code>을 받아와 Link의 herf와 일치하는지 확인할 수 있습니다.
다음 예시는 navigation에서 현재 페이지 Link를 파란색으로 표시하는 예제입니다.</p>
<pre><code class="language-jsx">&#39;use client&#39;

import { usePathname } from &#39;next/navigation&#39;
import Link from &#39;next/link&#39;

export function Navigation({ navLinks }) {
  const pathname = usePathname()

  return (
    &lt;&gt;
      {navLinks.map((link) =&gt; {
        const isActive = pathname === link.href

        return (
          &lt;Link
            className={isActive ? &#39;text-blue&#39; : &#39;text-black&#39;}
            href={link.href}
            key={link.name}
          &gt;
            {link.name}
          &lt;/Link&gt;
        )
      })}
    &lt;/&gt;
  )
}</code></pre>
<h3 id="3-id로-스크롤-하기">3. id로 스크롤 하기</h3>
<p>Next.js app 라우터는 기본적으로 새 라우트의 맨 위로 스크롤 되고, 이전페이지나 다음페이지로 이동 시 스크롤 위치를 유지합니다.</p>
<p>페이지 이동 시 특정 위치로 스크롤되게 하고싶은 경우 herf 속성의 URL 끝에 <code>#</code> 해시 링크를 추가하면됩니다. 이는 <code>&lt;Link&gt;</code>가 <code>&lt;a&gt;</code>태그처럼 렌더링되기 때문에 가능합니다.</p>
<pre><code class="language-jsx">&lt;Link href=&quot;/dashboard#settings&quot;&gt;Settings&lt;/Link&gt;

// Output
&lt;a href=&quot;/dashboard#settings&quot;&gt;Settings&lt;/a&gt;</code></pre>
<h3 id="4-스크롤-기본동작-비활성화">4. 스크롤 기본동작 비활성화</h3>
<p>새 라우트의 맨 위로 스크롤 되고, 이전페이지나 다음페이지로 이동 시 스크롤 위치를 유지하는 기본 동작을 비활성화하려면 <code>&lt;Link&gt;</code> 컴포넌트에 <code>scroll={false}</code> 속성을 넘기거나 <code>router.push()</code> 또는 <code>router.replace()</code>에 <code>scroll : false</code>를 넘기면 됩니다.</p>
<pre><code class="language-jsx">// next/link
&lt;Link href=&quot;/dashboard&quot; scroll={false}&gt;
  Dashboard
&lt;/Link&gt;</code></pre>
<pre><code class="language-jsx">// useRouter
import { useRouter } from &#39;next/navigation&#39;

router.push(&#39;/dashboard&#39;, { scroll: false })</code></pre>
<h1 id="userouter-hook">useRouter Hook</h1>
<p><code>useRouter</code> 훅은 클라이언트 컴포넌트에서만 사용가능하며 <code>next/nevigation</code>을 import 해야합니다.</p>
<pre><code class="language-jsx">&#39;use client&#39;

import { useRouter } from &#39;next/navigation&#39;

export default function Page() {
  const router = useRouter()

  return (
    &lt;button type=&quot;button&quot; onClick={() =&gt; router.push(&#39;/dashboard&#39;)}&gt;
      Dashboard
    &lt;/button&gt;
  )
}</code></pre>
<p>참고 - <a href="https://nextjs.org/docs/app/api-reference/functions/use-router">useRouter API docs</a></p>
<blockquote>
<p>참고 : <code>useRouter</code>을 사용해야하는 특별한 이유가 없으면 <code>&lt;Link&gt;</code>컴포넌트를 사용하는 것을 권장합니다.</p>
</blockquote>
<h1 id="routing과-navigation-동작-방식">Routing과 Navigation 동작 방식</h1>
<h2 id="1-prefetching-미리-가져오기">1. Prefetching (미리 가져오기)</h2>
<p><code>prefetching</code>은 사용자가 방문하기 전에 백그라운드에서 라우트를 미리 로드하는 방법입니다.</p>
<p>Next.js에는 라우트가 prefetch되는 두가지 방법이 있습니다.</p>
<ul>
<li><code>&lt;Link&gt; 컴포넌트</code>
Link컴포넌트가 사용자의 뷰포트에 표시될 경우 라우트는 자동으로 미리 로드됩니다. 페이지가 처음 로드되거나 스크롤을 통해 Link 컴포넌트가 표시될때 prefetch됩니다.</li>
<li><code>router.prefetch()</code>
<code>useRouter Hook</code>은 프로그래밍 방식으로 라우트를 prefetch 할 수 있습니다.</li>
</ul>
<p><code>&lt;Link&gt;</code>의 prefetch 방식은 static 라우트와 dynamic 라우트에 따라 차이가 있습니다.</p>
<ul>
<li><code>static 라우트</code>
prefetch 기본값이 <code>true</code>입니다. 전체 라우트가 prefetch되고 캐시됩니다.</li>
<li><code>dynamic 라우트</code>
prefetch 기본값은 <code>automatic</code>입니다. 첫 번째 <code>loading.js</code> 파일까지의 공유 레이아웃만 prefetch되고 30초 동안 캐시됩니다. 이것은 전체 다이나믹 라우트를 가져오는 비용을 줄이고 사용자에게 더 나은 시각적 피드백을 위해 즉각적인 로드 상태를 표시할 수 있음을 의미합니다.</li>
</ul>
<p>prefetch 속성을 <code>false</code>로 전달하면 prefetch를 비활성화 할 수 있습니다.</p>
<blockquote>
<p>참고 : prefetch는 개발환경에서는 동작하지 않으며, 프로덕션 환경에서만 동작합니다.</p>
</blockquote>
<h2 id="2-caching-캐싱">2. Caching (캐싱)</h2>
<p>Next.js는 <code>Router Cache</code>라는 <code>in-memory client-side cache</code>를 가지고 있습니다. 사용자가 라우트를 이동할 때, prefetch된 라우트 세그먼트와 방문한 라우트의 React Server 컴포넌트 페이로드가 캐시에 저장됩니다.</p>
<p>즉, 라우트 이동 시 서버에 새 요청을 하는 대신 캐시를 최대한 많이 재사용하여 요청 수와 전송되는 데이터를 줄임으로써 성능을 향상시킵니다.</p>
<h3 id="3-부분-렌더링">3. 부분 렌더링</h3>
<p>부분 렌더링은 페이지에서 변경되는 라우트 세그먼트만 클라이언트에서 다시 렌더링되고 모든 공유 세그먼트는 유지되는 것을 의미합니다.</p>
<p>예를 들어 두 개의 형제 라우트인 <code>/dashboard/settings</code> 와 <code>/dashboard/analytics</code> 사이를 이동할 때 <code>settings</code> 및 <code>analytics</code> 페이지가 다시 렌더링되며, 공유되는 <code>dashboard</code> 레이아웃은 유지됩니다.
<img src="https://velog.velcdn.com/images/zen_se/post/194682a7-be14-4651-a6f6-32cde65bd76c/image.png" alt=""></p>
<p>부분 렌더링이 없으면 이동할 때마다 전체 페이지가 서버에서 다시 렌더링됩니다. 변경되는 세그먼트만 렌더링하면 전송되는 데이터의 양과 실행 시간이 줄어들어 성능이 향상됩니다.</p>
<h3 id="4-soft-navigation">4. Soft Navigation</h3>
<p>기본적으로 브라우저는 페이지 사이를 이동할 때 <code>hard navigation</code>을 수행합니다. 이는 브라우저가 페이지를 다시 로드하고 앱의 <code>useState Hook</code> 과 같은 React state와 사용자의 스크롤 위치 또는 포커스된 요소와 같은 브라우저 state를 초기화함을 의미합니다.
그러나 App 라우터는 <code>soft navigation</code>을 사용합니다. 즉, 전체 페이지를 다시 로드하지 않고, React와 브라우저의 state를 유지하며 변경된 세그먼트만 리렌더링함을 의미합니다.</p>
<h3 id="5-이전다음-페이지-이동">5. 이전/다음 페이지 이동</h3>
<p>기본적으로 Next.js는 이전/다음 페이지 이동을 위한 스크롤 위치를 유지하고 라우터 캐시에서 라우트 세그먼트를 재사용합니다.</p>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating">https://nextjs.org/docs/app/building-your-application/routing/linking-and-navigating</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Routing - 페이지와 레이아웃]]></title>
            <link>https://velog.io/@zen_se/Routing-Pages-and-Layouts</link>
            <guid>https://velog.io/@zen_se/Routing-Pages-and-Layouts</guid>
            <pubDate>Mon, 14 Aug 2023 10:44:09 GMT</pubDate>
            <description><![CDATA[<h1 id="페이지와-레이아웃">페이지와 레이아웃</h1>
<p>Next.js 13의 app 라우터에서는 페이지, 공유 레이아웃, 템플릿을 쉽게 생성할 수 있는 새로운 파일 규칙을 도입했습니다. 이 페이지에서는 Next.js 애플리케이션에서 이러한 특수 파일을 어떻게 사용하는지 설명합니다.</p>
<h1 id="페이지">페이지</h1>
<p>페이지는 경로에 고유한 UI입니다. <code>page.js</code> 파일에서 컴포넌트를 export 해서 페이지를 정의할 수 있습니다. 폴더를 중첩시켜 경로를 정의하고 <code>page.js</code> 파일을 추가해 공개적으로 접근 가능하도록 만듭니다.</p>
<p><code>app</code> 디렉토리 내에 <code>page.js</code> 파일을 추가하여 첫 번째 페이지를 만듭니다.
<img src="https://velog.velcdn.com/images/zen_se/post/c73d34b9-d615-43f9-9da0-633d7583ee75/image.png" alt=""></p>
<pre><code class="language-jsx">/* app/page.js */

// `app/page.js` is the UI for the `/` URL
export default function Page() {
  return &lt;h1&gt;Hello, Home page!&lt;/h1&gt;
}</code></pre>
<pre><code class="language-jsx">/* app/dashboard/page.js */

// `app/dashboard/page.js` is the UI for the `/dashboard` URL
export default function Page() {
  return &lt;h1&gt;Hello, Dashboard Page!&lt;/h1&gt;
}</code></pre>
<blockquote>
<p>참고</p>
</blockquote>
<ul>
<li>페이지는 항상 라우트 서브트리의 리프입니다.</li>
<li><code>.js</code>, <code>.ts</code>, <code>.tsx</code> 확장자는 페이지 파일로 사용가능합니다.</li>
<li>경로 세그먼트를 공개적으로 액세스하려면 <code>page.js</code> 파일이 필요합니다.</li>
<li>페이지는 기본적으로 서버 컴포넌트이지만 클라이언트 컴포넌트로 설정할 수 있습니다.</li>
<li>페이지는 데이터를 fetch 할 수 있습니다.</li>
</ul>
<hr>
<h1 id="레이아웃">레이아웃</h1>
<p>레이아웃은 여러 페이지 간에 공유되는 UI입니다. 웹 페이지를 탐색 시 레이아웃은 state를 유지하고 대화형을 유지하며 리렌더링되지 않습니다. 레이아웃도 중첩될 수 있습니다.</p>
<p><code>layout.js</code> 파일에서 React 컴포넌트를 <code>default</code>로 export하여 레이아웃을 정의할 수 있습니다. 해당 컴포넌트는 렌더링 중에 자식 레이아웃(있는 경우) 또는 자식 페이지로 채워질 <code>children</code> prop을 가지고 있어야합니다.
<img src="https://velog.velcdn.com/images/zen_se/post/12e3a5ad-8afc-44ba-bcba-84e88f098db0/image.png" alt=""></p>
<pre><code class="language-jsx">/* app/dashboard/layout.js */

export default function DashboardLayout({
  children, // will be a page or nested layout
}) {
  return (
    &lt;section&gt;
      {/* Include shared UI here e.g. a header or sidebar */}
      &lt;nav&gt;&lt;/nav&gt;

      {children}
    &lt;/section&gt;
  )
}</code></pre>
<blockquote>
<p>참고</p>
</blockquote>
<ul>
<li>최상위 레이아웃을 <code>Root Layout</code>이라고 합니다. 루트 레이아웃은 반드시 존재해야하며, 항상 <code>html</code>과 <code>body</code>태그를 포함합니다. 루트 레이아웃은 애플리케이션의 모든 페이지에서 공유됩니다.</li>
<li>모든 경로 세그먼트에서는 선택적으로 자체 레이아웃을 정의할 수 있습니다. 이러한 레이아웃은 해당 세그먼트의 모든 페이지에서 공유됩니다.</li>
<li>경로의 레이아웃은 기본적으로 중첩됩니다. 각 부모 레이아웃은 <code>children</code> prop을 사용하여 그 아래에 있는 자식 레이아웃을 래핑합니다.</li>
<li>라우트 그룹을 사용하여 공유 레이아웃을 선택적으로 적용할 수 있습니다.</li>
<li>레이아웃은 기본적으로 서버 컴포넌트이지만 클라이언트 컴포넌트로 설정할 수 있습니다.</li>
<li>레이아웃은 데이터 fetch를 할 수 있습니다.</li>
<li>부모 레이아웃과 그 자식 간에는 데이터를 전달할 수 없습니다. 그러나 경로에서 동일한 데이터를 두 번 이상 가져올 수 있으며 React는 성능에 영향을 주지 않고 요청을 자동으로 중복 제거합니다.</li>
<li>레이아웃은 현재 라우트 세그먼트에 액세스할 수 없습니다. 라우트 세그먼트에 액세스하려면 클라이언트 컴포넌트에서 <code>useSelectedLayoutSegment</code> 또는 <code>useSelectedLayoutSegments</code>를 사용해야합니다.</li>
<li><code>.js</code>, <code>.ts</code>, <code>.tsx</code> 확장자는 레이아웃 파일로 사용가능합니다.</li>
<li><code>layout.js</code>와 <code>page.js</code> 파일은 동일한 폴더에 정의할 수 있습니다. 레이아웃은 페이지를 래핑합니다.</li>
</ul>
<h2 id="루트-레이아웃필수">루트 레이아웃(필수)</h2>
<p>루트 레이아웃은 <code>app</code> 디렉토리의 최상위에 정의되며 모든 경로에 적용됩니다. 이 레이아웃을 사용하면 서버에서 반환된 초기 HTML을 수정할 수 있습니다.</p>
<pre><code class="language-jsx">/* app/layout.js */

export default function RootLayout({ children }) {
  return (
    &lt;html lang=&quot;en&quot;&gt;
      &lt;body&gt;{children}&lt;/body&gt;
    &lt;/html&gt;
  )
}</code></pre>
<blockquote>
<p>참고</p>
</blockquote>
<ul>
<li><p><code>app</code> 디렉토리는 반드시 루트 레이아웃을 포함해야합니다.</p>
</li>
<li><p>루트 레이아웃에는 <code>html</code>과 <code>body</code> 태그가 반드시 포함되어야합니다. Next.js는 이를 자동으로 생성해주지 않습니다.</p>
</li>
<li><p>내장 SEO 지원을 사용해 <code>&lt;head&gt;</code> HTML 요소를 관리할 수 있습니다. ex) <code>&lt;title&gt;</code></p>
</li>
<li><p>라우트 그룹을 사용하여 복수의 루트 레이아웃을 생성할 수 있습니다.</p>
</li>
<li><p>루트 레이아웃은 기본적으로 서버 컴포넌트이며 클라이언트 레이아웃으로 설정할 수 없습니다.</p>
<h2 id="중첩-레이아웃">중첩 레이아웃</h2>
<p>폴더 안에 정의된 레이아웃(예: <code>app/dashboard/layout.js</code>)은 특정 라우트 세그먼트(예: <code>acme.com/dashboard</code>)에 적용되며 해당 세그먼트가 활성화될 때 렌더링됩니다. 기본적으로 파일 계층 구조의 레이아웃은 중첩됩니다. 즉, <code>children</code> prop을 통해 자식 레이아웃을 래핑합니다.
<img src="https://velog.velcdn.com/images/zen_se/post/9e9332d0-5f2e-443e-9a20-d10fe7eaee48/image.png" alt=""></p>
<pre><code class="language-jsx">/* app/dashboard/layout.js */
</code></pre>
</li>
</ul>
<p>export default function DashboardLayout({ children }) {
  return <section>{children}</section>
}</p>
<pre><code>
&gt; 참고
- `&lt;html&gt;`, `&lt;body&gt;`태그는 루트 레이아웃에만 사용할 수 있습니다.

위의 두 레이아웃을 결합하는 경우 루트 레이아웃(`app/layout.js`)은 대시보드 레이아웃(`app/dashboard/layout.js`)을 래핑하고, 대시보드 레이아웃은 `app/dashboard/*` 내부의 라우트 세그먼트를 래핑합니다.

두 레이아웃은 다음과 같이 중첩됩니다.
![](https://velog.velcdn.com/images/zen_se/post/7b32e8bb-8d27-4b7a-a7b6-1ea23804ce49/image.png)


또한, 라우트 그룹을 사용하여 공유 레이아웃을 선택적으로 적용할 수 있습니다.


# 템플릿(Templates)
템플릿은 하위 레이아웃 또는 페이지를 래핑한다는 점에서 레이아웃과 유사합니다. 경로 사이에서 지속되고 state를 유지하는 레이아웃과 달리 템플릿은 탐색 시 각 자식에 대해 새 인스턴스를 만듭니다. 즉, 사용자가 템플릿을 공유하는 라우트 사이를 탐색할 때 컴포넌트의 새 인스턴스가 마운트되고 DOM 요소가 다시 생성되며 state가 유지되지 않고 effect가 다시 동기화됩니다.

이러한 특정 동작이 필요한 경우가 있을 수 있으며, 다음같은 경우에 레이아웃보다 템플릿이 더 적합할 수 있습니다.
- CSS 또는 애니메이션 라이브러리를 사용한 시작/종료 애니메이션 사용
- `useEffect`와 `useState`에 의존하는 기능 사용
- 기본 프레임워크 동작을 변경하기 위해.
예를 들어 레이아웃 내부의 Suspense 경계는 페이지를 전환할 때가 아니라 레이아웃이 처음 로드될 때만 대체 페이지(fallback)를 표시합니다. 템플릿의 경우 각 탐색에 대체 페이지가 표시됩니다.

&gt; 템플릿을 사용할 특별한 이유가 없으면 레이아웃을 사용하는 것을 권장합니다.


템플릿은 `template.js` 파일에서 `default`로 React 컴포넌트를 export 해서 정의할 수 있습니다. 컴포넌트는 중첩된 세그먼트가 될 `children` prop을 가지고 있어야 합니다.
![](https://velog.velcdn.com/images/zen_se/post/c38dfa48-3397-404d-825c-ee38c96f6f1f/image.png)

```jsx
/* app/template.js */

export default function Template({ children }) {
  return &lt;div&gt;{children}&lt;/div&gt;
}</code></pre><p>레이아웃과 템플릿이 있는 라우트 세그먼트의 렌더링 결과는 다음과 같습니다.</p>
<pre><code class="language-jsx">&lt;Layout&gt;
  {/* Note that the template is given a unique key. */}
  &lt;Template key={routeParam}&gt;{children}&lt;/Template&gt;
&lt;/Layout&gt;</code></pre>
<h1 id="head-수정하기"><code>&lt;head&gt;</code> 수정하기</h1>
<p><code>app</code> 디렉토리에서 내장 SEO 지원을 사용하여 <code>title</code>이나 <code>meta</code>같은 <code>&lt;head&gt;</code> HTML 요소를 수정할 수 있습니다.</p>
<p>메타데이터는 <code>layout.js</code> 또는 <code>page.js</code> 파일에서 <code>metadata</code> 객체 또는 <code>generateMetadata</code> 함수를 export 해서 정의할 수 있습니다.</p>
<pre><code class="language-jsx">/* app/page.js */

export const metadata = {
  title: &#39;Next.js&#39;,
}

export default function Page() {
  return &#39;...&#39;
}</code></pre>
<blockquote>
<p>참고 : 루트 레이아웃에 <code>&lt;title&gt;</code>이나 <code>&lt;meta&gt;</code>같은 태그를 <code>&lt;head&gt;</code> 태그에 직접 추가하면 안됩니다. <code>&lt;head&gt;</code> 요소 스트리밍이나 중복 제거와 같은 기능을 자동으로 관리하는 Metadata API를 사용해야합니다.</p>
</blockquote>
<hr>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts">https://nextjs.org/docs/app/building-your-application/routing/pages-and-layouts</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Routing - 경로 정의하기]]></title>
            <link>https://velog.io/@zen_se/Routing-Defining-Routes</link>
            <guid>https://velog.io/@zen_se/Routing-Defining-Routes</guid>
            <pubDate>Mon, 14 Aug 2023 08:58:31 GMT</pubDate>
            <description><![CDATA[<h1 id="경로-정의하기">경로 정의하기</h1>
<p>이 페이지에서는 Next.js에서 어떻게 경로를 정의하고 구성하는지 설명합니다.</p>
<h1 id="경로-생성하기">경로 생성하기</h1>
<p>Next.js에서는 폴더가 경로를 정의하는데 사용되는 파일 시스템 기반의 라우터를 사용합니다.</p>
<p>각 폴더는 URL 세그먼트에 대응하는 라우트 세그먼트를 의미합니다. 폴더를 서로 중첩해서 중첩된 경로를 생성할 수 있습니다.
<img src="https://velog.velcdn.com/images/zen_se/post/cffecb9d-d884-4eb5-81cb-dd3bd23818b2/image.png" alt=""></p>
<p>경로 세그먼트에 공개적으로 접근할 수 있도록 특수 파일인 <code>page.js</code>가 사용됩니다.
<img src="https://velog.velcdn.com/images/zen_se/post/ce87668e-c5f4-43af-828b-45519c855f2f/image.png" alt=""></p>
<p>위의 그림에서 <code>/dashboard/analytics</code> URL은 해당 경로에 <code>page.js</code>파일이 존재하기 않기 때문에 공개적으로 접근할 수 없습니다. 이 폴더는 컴포넌트, 스타일시트, 이미지 또는 기타 파일을 저장하는 데 사용할 수 있습니다.</p>
<h1 id="ui-생성하기">UI 생성하기</h1>
<p>각 경로에서 UI를 생성하기 위해서는 특수한 파일 규칙이 사용됩니다. 가장 일반적인 것은 경로에 고유한 UI를 표시하는 페이지와 여러 경로에서 공유되는 UI를 표시하는 레이아웃입니다.</p>
<p>예를 들어, 첫 번째 페이지를 만들려면 app 디렉토리 내에 <code>page.js</code> 파일을 추가하고 React 컴포넌트를 export 합니다.</p>
<pre><code class="language-jsx">/* app/page.js */
export default function Page() {
  return &lt;h1&gt;Hello, Next.js!&lt;/h1&gt;
}</code></pre>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs/app/building-your-application/routing/defining-routes">https://nextjs.org/docs/app/building-your-application/routing/defining-routes</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Routing - 라우팅 기초]]></title>
            <link>https://velog.io/@zen_se/Routing-Routing-Fundamentals</link>
            <guid>https://velog.io/@zen_se/Routing-Routing-Fundamentals</guid>
            <pubDate>Mon, 14 Aug 2023 08:44:20 GMT</pubDate>
            <description><![CDATA[<h1 id="라우팅-기초">라우팅 기초</h1>
<p>모든 웹 애플리케이션의 뼈대는 라우팅입니다. 이 페이지에서는 웹 라우팅의 기본 개념과 Next.js에서 라우팅을 처리하는 방법을 소개합니다.</p>
<h1 id="용어">용어</h1>
<p>다음 용어들은 가이드 전체에서 사용되는 단어입니다.
<img src="https://velog.velcdn.com/images/zen_se/post/ccd72ed7-9056-4ebf-9c53-5378e89abd61/image.png" alt=""></p>
<ul>
<li>트리 : 계층 구조를 시각화하기 위한 규칙.
  ex) 컴포넌트 트리, 폴더 구조 등.</li>
<li>서브트리 : 새로운 루트에서 시작해서 리프노드에서 끝나는 트리의 일부.</li>
<li>루트 : 트리 또는 서브트리의 첫번째 노드.</li>
<li>리프 : 자식이 없는 서브트리의 노드.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/zen_se/post/2dd009b0-52dd-4c8c-a12f-319cf7be8b8e/image.png" alt=""></p>
<ul>
<li>URL 세그먼트 : <code>/</code>로 구분된 URL path의 일부</li>
<li>URL 경로(path) : 도메인 뒤에 오는 URL의 일부(세그먼트로 구성됨)</li>
</ul>
<h1 id="app-라우터">app 라우터</h1>
<p>버전 13에서 Next.js는 공유 레이아웃, 중첩 라우팅, 로드 상태, 에러처리 등을 지원하는 <code>React 서버 컴포넌트</code>를 기반으로 하는 <code>app 라우터</code>를 도입했습니다.</p>
<p>app 라우터는 <code>app</code>이라는 새로운 디렉토리에서 동작합니다. <code>app</code> 디렉토리는 점진적인 채택을 위해 <code>page</code> 디렉토리와 동시에 사용할 수 있습니다. 기존의 page 라우터를 사용하는 어플리케이션에서 일부 경로만 app 라우터로 변경할 수 있습니다. 만약 어플리케이션이 page 디렉토리를 사용한다면 page 라우터 문서를 참조하세요.
(번역은 app 라우터 문서입니다)</p>
<blockquote>
<p>참고 - app 라우터가 page 라우터보다 우선순위가 높습니다. 동일한 URL 경로를 가진 디렉토리가 존재하면 빌드타임 에러가 발생합니다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/zen_se/post/fbae3326-f866-43ab-b816-22ba3b353cbf/image.png" alt="">
<code>app</code> 내부의 컴포넌트는 기본적으로 모두 <code>React Server Component</code>입니다. 이는 성능 최적화하고 app 라우터를 도입을 쉬워지게 합니다. 또한 클라이언트 컴포넌트도 사용가능합니다.</p>
<h1 id="폴더와-파일의-역할">폴더와 파일의 역할</h1>
<p>Next.js는 파일시스템 기반 라우터를 사용합니다.
<code>폴더</code>는 경로를 정의하는데 사용됩니다. 경로는 루트 폴더에서 <code>page.js</code> 파일을 포함하는 마지막 리프 폴더까지 파일 시스템 계층 구조를 따르는 중첩 폴더의 단일 경로입니다.
<code>파일</code>은 경로 세그먼트에 대해 표시되는 UI를 만드는 데 사용됩니다.</p>
<h1 id="경로-세그먼트-route-segments">경로 세그먼트 (route segments)</h1>
<p>경로의 각 폴더는 경로 세그먼트를 의미합니다. 각 경로 세그먼트는 URL path의 해당 세그먼트에 매핑됩니다.
<img src="https://velog.velcdn.com/images/zen_se/post/b134837c-db7f-4c32-8d3b-83aa22df9c28/image.png" alt=""></p>
<h1 id="중첩된-경로-nested-routes">중첩된 경로 (nested routes)</h1>
<p>폴더를 서로 중첩해서 중첩된 경로를 만들 수 있습니다. 예를 들어 app 디렉토리에 두 개의 새 폴더를 중첩하여 새로운 <code>/dashboard/settings</code> 경로를 추가할 수 있습니다.</p>
<p><code>/dashboard/settings</code> 경로는 <code>/</code>(루트 세그먼트), <code>dashboard</code>(세그먼트), <code>settings</code>(리프 세그먼트)의 3개의 세그먼트로 구성됩니다.</p>
<h1 id="파일-컨벤션">파일 컨벤션</h1>
<p>Next.js는 특정 동작으로 UI를 생성하기 위한 특수 파일 집합을 제공합니다.</p>
<ul>
<li><code>layout</code> : 해당 세그먼트와 하위 세그먼트에 공유되는 UI.</li>
<li><code>page</code> : 해당 경로의 고유한 UI. 해당 경로를 공개적으로 접근 가능하도록 만듦</li>
<li><code>loading</code> : 해당 세그먼트와 하위 세그먼트의 로딩 UI.</li>
<li><code>not-found</code> : 해당 세그먼트와 하위 세그먼트의 Not found UI.</li>
<li><code>error</code> : 해당 세그먼트와 하위 세그먼트의 Error UI.</li>
<li><code>global-error</code> : 글로벌 Error UI.</li>
<li><code>route</code> : 서버사이드 API 엔드포인트.</li>
<li><code>template</code> : 리렌더링에 특화된 레이아웃 UI.</li>
<li><code>default</code> : 병렬 라우트의 대체 UI</li>
</ul>
<p>위 파일들은 <code>.js</code>, <code>.jsx</code>, <code>.tsx</code> 확장자를 가질 수 있습니다.</p>
<h1 id="컴포넌트-계층-구조">컴포넌트 계층 구조</h1>
<p>경로 세그먼트에 특수 파일로 정의된 React 컴포넌트는 다음과 같은 특정한 계층으로 렌더링됩니다.
<img src="https://velog.velcdn.com/images/zen_se/post/ff32f68e-58ca-494d-8f08-3debf1049865/image.png" alt=""></p>
<p>중첩된 경로에서 세그먼트의 컴포넌트는 상위 세그먼트의 컴포넌트 내에 중첩됩니다.
<img src="https://velog.velcdn.com/images/zen_se/post/f246f307-ef1a-407a-b46d-bc2cfebc9260/image.png" alt=""></p>
<h1 id="같이-배치하기-colocation">같이 배치하기 (Colocation)</h1>
<p>특수 파일 외에도 app 디렉토리의 폴더 안에 다른 파일(예: 컴포넌트, 스타일, 테스트 등)을 함께 배치할 수 있습니다.</p>
<p>이는 폴더에서 경로가 정의될 때 <code>page.js</code> 또는 <code>route.js</code>에서 반환된 콘텐츠만 주소를 가지기 때문입니다.
<img src="https://velog.velcdn.com/images/zen_se/post/a342d3e0-9e2d-41cd-9b81-17656cf0baad/image.png" alt=""></p>
<h1 id="고급-라우팅-패턴">고급 라우팅 패턴</h1>
<p>app 라우터는 고급 라우팅 패턴 구현을 위한 몇몇 컨벤션을 제공합니다.</p>
<ul>
<li>병렬 라우트(Parallel Route)
독립적인 두개 이상의 페이지를 동시에 같은 뷰에서 
보여줄 수 있습니다. 자체 서브 네비게이션을 가진 분할 뷰에 사용할 수 있습니다. ex) 대시보드</li>
<li>라우트 가로채기(Intercepting Route)
라우트를 가로채서 다른 라우트의 컨텍스트에서 표시합니다. 현재 페이지의 컨텍스트를 유지하는 것이 중요할 때 사용할 수 있습니다.
ex) 하나의 작업중에 전체 작업보기, 피드에서 사진을 확대해서 보기</li>
</ul>
<p>이 패턴들은 더 풍부하고 복잡한 UI를 구축할 수 있게 해주며, 소규모 팀과 개인 개발자에게 복잡했던 기능을 구현하는데 도움이 됩니다.</p>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs/app/building-your-application/routing">https://nextjs.org/docs/app/building-your-application/routing</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[시작하기 - React 요점]]></title>
            <link>https://velog.io/@zen_se/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-React-Essentials</link>
            <guid>https://velog.io/@zen_se/%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-React-Essentials</guid>
            <pubDate>Tue, 08 Aug 2023 11:47:37 GMT</pubDate>
            <description><![CDATA[<h1 id="react-요점">React 요점</h1>
<p>Next.js로 애플리케이션을 구축하려면 <code>Server Component</code>와 같은 React의 최신 기능에 익숙해지는 것이 도움이 됩니다. 이 페이지에서는 <code>Server Component</code>와 <code>Client Component</code>의 차이점, 사용 시기 및 권장 패턴을 살펴봅니다.</p>
<p>React를 처음 사용하는 경우 React Docs도 참조하는 것이 좋습니다. 다음은 React 학습을 위한 좋은 자료입니다.</p>
<ul>
<li><a href="https://react-ko.dev/learn/tutorial-tic-tac-toe">React 튜토리얼</a></li>
<li><a href="https://react-ko.dev/learn/thinking-in-react">React로 사고하기</a></li>
<li><a href="https://react-ko.dev/learn/describing-the-ui">React 배우기</a></li>
</ul>
<hr>
<h1 id="server-component">Server Component</h1>
<p>서버 및 클라이언트 컴포넌트를 사용하면 개발자가 서버와 클라이언트에 걸쳐 있는 애플리케이션을 구축하여 클라이언트 사이드 앱의 풍부한 상호 작용과 기존 서버 렌더링의 향상된 성능을 결합할 수 있습니다.</p>
<h2 id="server-component로-생각하기">Server Component로 생각하기</h2>
<p>React가 UI 구축에 대한 생각 방식을 어떻게 바꾸었는지와 유사하게 <code>React Server Component</code>는 서버와 클라이언트를 활용하는 하이브리드 애플리케이션을 구축하기 위한 새로운 사고 모델을 소개합니다.</p>
<p>React는 전체 애플리케이션을 클라이언트 사이드 렌더링(SPA 같은)하는 대신 이제 목적에 따라 컴포넌트를 렌더링할 위치를 선택할 수 있는 유연성을 제공합니다.</p>
<p>예를 들어 다음과 같은 애플리케이션의 경우,
<img src="https://velog.velcdn.com/images/zen_se/post/a202e063-a05d-42df-a5db-b61785b09553/image.png" alt="">
페이지를 더 작은 구성 요소로 분할하면 대부분의 구성 요소가 비대화형이며 서버 컴포넌트로 서버에서 렌더링될 수 있음을 알 수 있습니다.
작은 대화형 UI의 경우는 클라이언트 컴포넌트로 <em>뿌릴</em> 수 있습니다. 이것은 Next.js 서버 우선 접근 방식과 일치합니다.</p>
<h2 id="서버-컴포넌트를-사용하는-이유">서버 컴포넌트를 사용하는 이유</h2>
<p>그렇다면 왜 서버 컴포넌트를 사용할까? 클라이언트 컴포넌트에 비해 서버 컴포넌트를 사용하면 어떤 이점이 있을까?</p>
<p>서버 컴포넌트를 통해 개발자는 서버 인프라를 더 잘 활용할 수 있습니다. 
예를 들어, 데이터 페칭을 데이터베이스에 가까운 서버로 이전하고, 이전에는 서버의 클라이언트 JavaScript 번들 크기에 영향을 주었던 큰 종속성을 유지하여 성능을 향상시킬 수 있습니다.
서버 컴포넌트를 사용하면 React 애플리케이션을 작성하는 것이 PHP 또는 Ruby on Rails와 유사하게 느껴질 수 있지만, React의 강력함과 유연성 및 템플릿 UI용 컴포넌트 모델을 가지고 있습니다.</p>
<p>서버 컴포넌트를 사용하면 초기 페이지 로드가 더 빨라지고 클라이언트 사이드 JavaScript 번들 크기가 줄어듭니다. 기본 클라이언트 사이드 런타임은 캐시 가능하고 예측가능한 크기이며 애플리케이션이 커져도 늘어나지 않습니다. 추가적인 JavaScript는 클라이언트 컴포넌트를 통해 애플리케이션에서 클라이언트 측 상호 작용이 사용되는 경우에만 추가됩니다.</p>
<p>Next.js로 로드되면, 초기 HTML은 서버에서 렌더링 됩니다. 그런 다음 이 HTML은 브라우저에서 점진적으로 향상되어 클라이언트가 Next.js 및 React 클라이언트 사이드 런타임을 비동기적으로 로드하여 애플리케이션을 넘겨받고 상호작용을 추가할 수 있습니다.</p>
<p>서버 컴포넌트로 전환을 더 쉽게 하기 위해 앱 라우터 내부의 모든 구성 요소는 <code>특수 파일(layout.tsx, page.tsx 등)</code> 및 <code>공동 배치 컴포넌트(colocated component - app 디렉토리 내 특수 파일을 제외한 다른 파일들)</code>를 포함하여 기본적으로 서버 구성 요소입니다.
이를 통해 추가 작업 없이 자동으로 서버 컴포넌트를 즉시 사용해 뛰어난 성능을 얻을 수 있습니다. 또한 &#39;use client&#39; 지시문을 사용하여 선택적으로 클라이언트 컴포넌트로 사용할 수 있습니다.</p>
<hr>
<h1 id="클라이언트-컴포넌트">클라이언트 컴포넌트</h1>
<p>클라이언트 구성 요소를 사용하면 애플리케이션에 클라이언트 측 상호 작용을 추가할 수 있습니다.
Next.js는 서버에서 미리 렌더링되고 클라이언트에서 <code>수화(hydration)</code>됩니다. 페이지 라우터의 구성 요소가 항상 작동하는 방식으로 클라이언트 구성 요소를 생각할 수 있습니다.</p>
<h2 id="use-client-지시문">&#39;use client&#39; 지시문</h2>
<p><code>&#39;use client&#39;</code> 지시문은 서버와 클라이언트 컴포넌트 모듈 그래프 사이의 경계를 선언하는 규칙입니다.</p>
<pre><code class="language-tsx">&#39;use client&#39;

import { useState } from &#39;react&#39;

export default function Counter() {
  const [count, setCount] = useState(0)

  return (
    &lt;div&gt;
      &lt;p&gt;You clicked {count} times&lt;/p&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;Click me&lt;/button&gt;
    &lt;/div&gt;
  )
}</code></pre>
<p><img src="https://velog.velcdn.com/images/zen_se/post/8b13fca6-231b-4cb8-b6d4-1f69636bef3a/image.png" alt=""></p>
<p>&#39;use clinet&#39; 지시문은 서버 전용 코드와 클라이언트 코드 사이에 위치합니다. 서버와 클라이언트 코드의 경계를 정의하기 위해 import 보다 위인 파일의 최상단에 위치합니다. &#39;use clinet&#39; 지시문이 파일에 정의되면 자식 컴포넌트를 포함하여 import된 다른 모든 모듈은 클라이언트 번들의 일부로 간주됩니다.</p>
<p>서버 컴포넌트가 기본값이므로 &quot;use client&quot; 지시문으로 시작하는 모듈에서 정의하거나 가져오지 않는 한 모든 컴포넌트는 서버 컴포넌트 모듈 그래프의 일부입니다.</p>
<blockquote>
</blockquote>
<p>알아두면 좋은 정보: </p>
<ul>
<li>서버 구성 요소 모듈 그래프의 구성 요소는 서버에서만 렌더링되도록 보장됩니다.</li>
<li>클라이언트 컴포넌트 모듈 그래프의 구성 요소는 주로 클라이언트에서 렌더링되지만 Next.js를 사용하면 서버에서 사전 렌더링되고 클라이언트에서 수화될 수도 있습니다.</li>
<li>반드시 파일 최상단에 <code>&#39;use client&#39;</code>를 정의해야 합니다.</li>
<li><code>&#39;use clinet&#39;</code>는 모든 파일에서 정의할 필요가 없습니다. 클라이언트 모듈 경계는 진입점에서 한 번만 정의하면 클라이언트 컴포넌트로 간주되는 모든 모듈을 가져올 수 있습니다.</li>
</ul>
<h2 id="언제-서버-or-클라이언트-컴포넌트를-사용해야할까">언제 서버 or 클라이언트 컴포넌트를 사용해야할까</h2>
<p>클라이언트 컴포넌트를 사용해야 할 케이스가 없다면 app 디렉토리의 기본값인 서버 컴포넌트를 사용하는 것을 추천합니다.</p>
<p>다음 표에는 서버 및 클라이언트 컴포넌트의 다양한 사용 사례가 요약되어 있습니다.</p>
<table>
<thead>
<tr>
<th align="left">요구 상황</th>
<th align="center">서버 컴포넌트</th>
<th align="center">클라이언트 컴포넌트</th>
</tr>
</thead>
<tbody><tr>
<td align="left">데이터 가져오기</td>
<td align="center">O</td>
<td align="center">X</td>
</tr>
<tr>
<td align="left">백엔드 리소스 접근(직접)</td>
<td align="center">O</td>
<td align="center">X</td>
</tr>
<tr>
<td align="left">민감한 정보 서버에서 보관(액세스 토큰, API key 등)</td>
<td align="center">O</td>
<td align="center">X</td>
</tr>
<tr>
<td align="left">서버에 대한 큰 종속성 유지 / 클라이언트 측 JavaScript 줄이기</td>
<td align="center">O</td>
<td align="center">X</td>
</tr>
<tr>
<td align="left">상호작용이나 이벤트 리스너 추가(onClick(), onChange() 등)</td>
<td align="center">X</td>
<td align="center">O</td>
</tr>
<tr>
<td align="left">State나 LifeCycle Effect 사용(useState(), useReducer(), useEffect() 등)</td>
<td align="center">X</td>
<td align="center">O</td>
</tr>
<tr>
<td align="left">브라우저 전용 API 사용</td>
<td align="center">X</td>
<td align="center">O</td>
</tr>
<tr>
<td align="left">state, effect, 브라우저 API 기반 커스텀 훅 사용</td>
<td align="center">X</td>
<td align="center">O</td>
</tr>
<tr>
<td align="left">React 클래스 컴포넌트 사용</td>
<td align="center">X</td>
<td align="center">O</td>
</tr>
</tbody></table>
<h1 id="사용-예">사용 예</h1>
<h2 id="클라이언트-컴포넌트를-리프로-이동하기">클라이언트 컴포넌트를 리프로 이동하기</h2>
<p>애플리케이션의 성능을 향상시키기 위해 가능한 클라이언트 컴포넌트를 컴포넌트 트리의 리프로 이동하는 것이 좋습니다.</p>
<p>예를 들어 정적 요소(예: 로고, 링크 등)가 있는 레이아웃과 state를 사용하는 대화형 검색 표시줄이 있을 수 있습니다.</p>
<p>전체 레이아웃을 클라이언트 컴포넌트로 만드는 대신 상호작용 로직을 클라이언트 컴포넌트(예: <code>&lt;SearchBar /&gt;</code>)로, 레이아웃을 서버 컴포넌트로 유지합니다. 즉, 레이아웃의 모든 컴포넌트의 Javascript를 클라이언트에 보낼 필요가 없음을 의미합니다.</p>
<pre><code class="language-jsx">// SearchBar is a Client Component
import SearchBar from &#39;./searchbar&#39;
// Logo is a Server Component
import Logo from &#39;./logo&#39;

// Layout is a Server Component by default
export default function Layout({ children }) {
  return (
    &lt;&gt;
      &lt;nav&gt;
        &lt;Logo /&gt;
        &lt;SearchBar /&gt;
      &lt;/nav&gt;
      &lt;main&gt;{children}&lt;/main&gt;
    &lt;/&gt;
  )
}</code></pre>
<h2 id="서버-및-클라이언트-컴포넌트-조합하기">서버 및 클라이언트 컴포넌트 조합하기</h2>
<p>서버 및 클라이언트 컴포넌트는 동일한 컴포넌트 트리에서 결합될 수 있습니다.</p>
<p>React는 다음과 같이 렌더링을 처리합니다.</p>
<ol>
<li>서버에서 React는 클라이언트에 결과를 보내기 전에 모든 서버 컴포넌트를 렌더링합니다.</li>
</ol>
<ul>
<li>여기에는 클라이언트 컴포넌트 내에 중첩된 서버 컴포넌트가 포함됩니다.</li>
<li>이 단계에서 마주친 클라이언트 컴포넌트는 건너뜁니다.</li>
</ul>
<ol start="2">
<li>클라이언트에서 React는 서버 컴포넌트의 렌더링된 결과에서 클라이언트 컴포넌트와 슬롯을 렌더링하여 서버와 클라이언트에서 수행된 작업을 병합합니다.</li>
</ol>
<ul>
<li>서버 컴포넌트가 클라이언트 컴포넌트 내에 중첩된 경우 렌더링된 콘텐츠는 클라이언트 구성 요소 내에 올바르게 배치됩니다.</li>
</ul>
<blockquote>
<p>알아두면 좋은 정보: Next.js에서는 초기 페이지를 더 빠르게 로드하기 위해 초기 페이지 로드 중에 위 단계에서 서버 컴포넌트의 렌더링된 결과와 클라이언트 컴포넌트가 모두 서버에서 HTML로 미리 렌더링됩니다.</p>
</blockquote>
<h2 id="클라이언트-컴포넌트-내부에-중첩된-서버-컴포넌트">클라이언트 컴포넌트 내부에 중첩된 서버 컴포넌트</h2>
<p>위에서 설명한 렌더링 흐름을 고려할 때 서버 컴포넌트를 클라이언트 컴포넌트에 import 하는데는 제한이 있습니다. 이 방식에는 추가적인 서버 왕복(round trip)이 필요하기 때문입니다.</p>
<h3 id="지원되지-않는-패턴-서버-컴포넌트를-클라이언트-컴포넌트에-import하기">지원되지 않는 패턴: 서버 컴포넌트를 클라이언트 컴포넌트에 import하기</h3>
<p>다음 패턴은 지원되지 않습니다. 서버 컴포넌트를 클라이언트 컴포넌트로 import 할 수 없습니다.</p>
<pre><code class="language-jsx">&#39;use client&#39;

// This pattern will **not** work!
// You cannot import a Server Component into a Client Component.
import ExampleServerComponent from &#39;./example-server-component&#39;

export default function ExampleClientComponent({ children }) {
  const [count, setCount] = useState(0)

  return (
    &lt;&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;{count}&lt;/button&gt;

      &lt;ExampleServerComponent /&gt;
    &lt;/&gt;
  )
}</code></pre>
<h3 id="권장-패턴-서버-컴포넌트를-props로-클라이언트-컴포넌트에-전달">권장 패턴: 서버 컴포넌트를 Props로 클라이언트 컴포넌트에 전달</h3>
<p>대신 클라이언트 컴포넌트를 디자인할 때 React Props을 사용하여 서버 컴포넌트의 &quot;슬롯&quot;을 표시할 수 있습니다.</p>
<p>서버 컴포넌트는 서버에서 렌더링되고 클라이언트 컴포넌트가 클라이언트에서 렌더링될 때 &quot;슬롯&quot;은 서버 컴포넌트의 렌더링된 결과로 채워집니다.</p>
<p>일반적인 패턴은 React <code>children</code> prop을 사용하여 &quot;슬롯&quot;을 만드는 것입니다.
<code>&lt;ExampleClientComponent&gt;</code>가 <code>children</code> prop을 받도록 하고 <code>&lt;ExampleClientComponent&gt;</code>의 import 및 명시적 중첩을 상위 컴포넌트로 이동합니다.</p>
<pre><code class="language-jsx">&#39;use client&#39;

import { useState } from &#39;react&#39;

export default function ExampleClientComponent({ children }) {
  const [count, setCount] = useState(0)

  return (
    &lt;&gt;
      &lt;button onClick={() =&gt; setCount(count + 1)}&gt;{count}&lt;/button&gt;

      {children}
    &lt;/&gt;
  )
}</code></pre>
<p>이제 <code>&lt;ExampleClientComponent&gt;</code>는 <code>children</code>에 무엇이 올지 알 수 없습니다. <code>children</code>이 서버 컴포넌트로 채워질 것이라는 사실을 모릅니다.</p>
<p><code>&lt;ExampleClientComponent&gt;</code>의 책임은 <code>children</code>이 배치될 위치를 결정하는 것입니다.</p>
<p>부모 서버 컴포넌트에서는 <code>&lt;ExampleClientComponent&gt;</code> 와 <code>&lt;ExampleServerComponent&gt;</code> 두 가지를 모두 import 할 수 있습니다. 그리고 <code>&lt;ExampleServerComponent&gt;</code>를 <code>&lt;ExampleClientComponent&gt;</code>의 <code>children</code>으로 넘겨줍니다.</p>
<pre><code class="language-jsx">// This pattern works:
// You can pass a Server Component as a child or prop of a
// Client Component.
import ExampleClientComponent from &#39;./example-client-component&#39;
import ExampleServerComponent from &#39;./example-server-component&#39;

// Pages in Next.js are Server Components by default
export default function Page() {
  return (
    &lt;ExampleClientComponent&gt;
      &lt;ExampleServerComponent /&gt;
    &lt;/ExampleClientComponent&gt;
  )
}</code></pre>
<p>이 접근법을 사용하면 <code>&lt;ExampleClientComponent&gt;</code>와 <code>&lt;ExampleServerComponent&gt;</code>의 렌더링이 분리되어 클라이언트 컴포넌트보다 먼저 서버에서 렌더링되는 서버 컴포넌트에 맞추어 독립적으로 렌더링될 수 있습니다.</p>
<blockquote>
</blockquote>
<p>알아두면 좋은 정보: </p>
<ul>
<li>이 패턴은 <code>children</code> prop이 있는 레이아웃 및 페이지에 이미 적용되어 있으므로 추가 래퍼 컴포넌트를 만들 필요가 없습니다.</li>
<li>React 컴포넌트(JSX)를 다른 컴포넌트로 전달하는 것은 새로운 개념이 아니며 항상 React 모델의 일부였습니다.</li>
<li>이 방법은 prop을 받는 컴포넌트가 prop이 무엇인지 알지 못하기 때문에 서버 및 클라이언트 컴포넌트에서 작동합니다. 오직 전달받은 것을 어디에 두어야 하는지에 대해서만 책임이 있습니다.<ul>
<li>이렇게 하면 클라이언트 컴포넌트가 클라이언트에서 렌더링되기 훨씬 전에 서버에서 전달된 prop을 독립적으로 렌더링할 수 있습니다.</li>
<li>import된 child 컴포넌트를 다시 렌더링하는 부모 컴포넌트의 상태 변경을 방지하기 위해 <code>콘텐츠 끌어 올리기</code>와 동일한 전략이 사용되었습니다.</li>
</ul>
</li>
<li><code>children</code> prop뿐만 아니라 모든 prop을 사용하여 JSX를 넘겨줄 수 있습니다.</li>
</ul>
<h2 id="서버에서-클라이언트-컴포넌트로-props-전달직렬화">서버에서 클라이언트 컴포넌트로 props 전달(직렬화)</h2>
<p>서버에서 클라이언트 컴포넌트로 전달되는 prop은 직렬화가 가능해야 합니다. 이는 함수, 날짜같은 값을 클라이언트 컴포넌트에 직접 전달할 수 없음을 의미합니다.</p>
<blockquote>
<p>네트워크 경계(Network Boundary)는 어디 위치할까요?
앱 라우터에서 네트워크 경계는 서버 컴포넌트와 클라이언트 컴포넌트 사이에 위치합니다. 이는 <code>getStaticProps</code>/<code>getServerSideProps</code>와 페이지 컴포넌트 사이에 위치하는 페이지 라우터와의 차이점입니다. 서버 컴포넌트에 포함된 데이터 요청은 클라이언트 컴포넌트와 다르게 네트워크 경계를 넘지 않기 때문에 직렬화될 필요가 없습니다.</p>
</blockquote>
<h2 id="서버전용-코드를-클라이언트-컴포넌트에서-제외하기">서버전용 코드를 클라이언트 컴포넌트에서 제외하기</h2>
<p>JavaScript 모듈은 서버 및 클라이언트 컴포넌트간에 공유될 수 있으므로 서버에서만 실행되도록 의도된 코드가 클라이언트에 의도치 않게 포함될 수 있습니다.</p>
<p>예를 들어, 다음같은 데이터 페칭 함수에서:</p>
<pre><code class="language-jsx">export async function getData() {
  const res = await fetch(&#39;https://external-service.com/data&#39;, {
    headers: {
      authorization: process.env.API_KEY,
    },
  })

  return res.json()
}</code></pre>
<p><code>getData()</code>가 서버와 클라이언트에서 모두 동작할 것처럼 보이지만, 환경 변수 <code>API_KEY</code>에 접두사 <code>NEXT_PUBLIC</code>이 없기 때문에 서버에서만 접근할 수 있는 private 변수입니다. Next.js는 클라이언트 코드에서 private 변수는 빈 문자열로 대체하여 보안 정보 유출을 방지합니다.</p>
<p>결과적으로 <code>getData()</code>는 클라이언트에서 import와 export는 될 수 있지만 의도대로 동작하지 않을 것입니다. 그리고 환경 변수를 public으로 변경하면 동작은 하지만 민감한 정보가 유출됩니다.</p>
<p>따라서 이 함수는 서버에서만 실행하도록 의도하여 작성되었습니다.</p>
<h2 id="server-only-패키지">&quot;server only&quot; 패키지</h2>
<p>이러한 의도하지 않은 클라이언트에서 서버 코드 사용을 방지하기 위해 <code>server-only</code> 패키지를 사용하여 다른 개발자가 실수로 이러한 모듈 중 하나를 클라이언트 컴포넌트로 가져온 경우 빌드 타임 오류를 발생시킬 수 있습니다.</p>
<p><code>server-only</code> 패키지를 사용하기 위해 먼저 설치합니다.</p>
<ul>
<li><code>npm install server-only</code></li>
</ul>
<p>그리고 서버 전용 코드가 포함된 모듈에 import 합니다.</p>
<pre><code class="language-jsx">import &#39;server-only&#39;

export async function getData() {
  const res = await fetch(&#39;https://external-service.com/data&#39;, {
    headers: {
      authorization: process.env.API_KEY,
    },
  })

  return res.json()
}</code></pre>
<p>이제 <code>getData()</code>를 import 하는 모든 클라이언트 컴포넌트는 <code>이 모듈은 서버에서만 사용될 수 있습니다</code>라는 빌드타임 에러를 수신합니다.</p>
<p>이에 상응하는 <code>client-only</code> 패키지는 클라이언트 전용 코드를 포함하는 모듈을 표시하는 데 사용할 수 있습니다. ex) <code>window</code> 객체에 접근하는 코드</p>
<h2 id="데이터-페칭fetching">데이터 페칭(Fetching)</h2>
<p>클라이언트 컴포넌트에서 데이터를 페치할 수 있지만 클라이언트에서 데이터를 페칭해야 하는 특별한 이유가 없는 한 서버 컴포넌트에서 데이터를 페칭하는 것이 좋습니다. 데이터 페칭을 서버로 이동하면 성능과 사용자 경험이 향상됩니다.</p>
<h2 id="서드파티-패키지">서드파티 패키지</h2>
<p>서버 컴포넌트가 새로운 개념이기 때문에 같은 생태계의 서드파티 패키지는 <code>useState</code>, <code>useEffect</code> 및 <code>createContext</code>와 같은 클라이언트 전용 기능을 사용하는 컴포넌트에 <code>&quot;use client&quot;</code> 지시문을 추가하기 시작했습니다.</p>
<p>현재 클라이언트 전용 기능을 사용하는 npm 패키지의 많은 컴포넌트에는 아직 지시문이 없습니다. 이러한 서드파티 패키지는 <code>&quot;use client&quot;</code> 지시문이 있는 클라이언트 컴포넌트 내에서는 예상대로 작동하지만 서버 컴포넌트 내에서는 작동하지 않습니다.</p>
<p>예를 들어 <code>&lt;Carousel /&gt;</code> 컴포넌트를 가진 가상의 <code>acme-carousel</code> 패키지를 설치했다고 가정해 보겠습니다. 이 컴포넌트는 useState를 사용하지만 아직 <code>&quot;use client&quot;</code> 지시문이 없습니다.</p>
<p>클라이언트 컴포넌트에서 <code>&lt;Carousel /&gt;</code>를 사용하면 예상한대로 동작합니다.</p>
<pre><code class="language-jsx">&#39;use client&#39;

import { useState } from &#39;react&#39;
import { Carousel } from &#39;acme-carousel&#39;

export default function Gallery() {
  let [isOpen, setIsOpen] = useState(false)

  return (
    &lt;div&gt;
      &lt;button onClick={() =&gt; setIsOpen(true)}&gt;View pictures&lt;/button&gt;

      {/*  Works, since Carousel is used within a Client Component */}
      {isOpen &amp;&amp; &lt;Carousel /&gt;}
    &lt;/div&gt;
  )
}</code></pre>
<p>그러나 서버 컴포넌트에서 직접 사용하려고 하면 에러가 발생합니다.</p>
<pre><code class="language-jsx">import { Carousel } from &#39;acme-carousel&#39;

export default function Page() {
  return (
    &lt;div&gt;
      &lt;p&gt;View pictures&lt;/p&gt;

      {/*  Error: `useState` can not be used within Server Components */}
      &lt;Carousel /&gt;
    &lt;/div&gt;
  )
}</code></pre>
<p>그 이유는 Next.js가 <code>&lt;Carousel /&gt;</code>가 클라이언트 전용 기능을 사용하고 있는 것을 알지 못하기 때문입니다.</p>
<p>이 문제를 해결하려면 클라이언트 컴포넌트에서 클라이언트 전용 기능에 의존하는 서드파티 컴포넌트를 래핑할 수 있습니다.</p>
<pre><code class="language-jsx">&#39;use client&#39;

import { Carousel } from &#39;acme-carousel&#39;

export default Carousel</code></pre>
<p>이제 <code>&lt;Carousel /&gt;</code>를 서버 컴포넌트에서 직접 사용할 수 있습니다.</p>
<pre><code class="language-jsx">import Carousel from &#39;./carousel&#39;

export default function Page() {
  return (
    &lt;div&gt;
      &lt;p&gt;View pictures&lt;/p&gt;

      {/*  Works, since Carousel is a Client Component */}
      &lt;Carousel /&gt;
    &lt;/div&gt;
  )
}</code></pre>
<p>대부분의 서드파티 컴포넌트는 클라이언트 컴포넌트 내에서 사용할 가능성이 높으므로 래핑할 필요는 없습니다. 그러나 한 가지 예외가 있는데 공급자 컴포넌트(provider component)입니다. 이는 React <code>state</code> 및 <code>context</code>에 의존하고 일반적으로 애플리케이션의 루트에 필요하기 때문입니다.</p>
<h3 id="라이브러리-작성">라이브러리 작성</h3>
<ul>
<li>라이브러리 작성자는 <code>&quot;use client&quot;</code> 지시문을 사용하여 패키지의 클라이언트 진입점을 표시할 수 있습니다. 이를 통해 패키지를 래핑하지 않고도 패키지의 컴포넌트를 서버 컴포넌트로 직접 import 할 수 있습니다.</li>
<li>가져온 모듈이 서버 컴포넌트 모듈 그래프의 일부가 되도록 트리에서 더 깊은<code>&quot;use client&quot;</code>을 사용하여 패키지를 최적화할 수 있습니다.</li>
<li>일부 번들러가 <code>&quot;use client&quot;</code> 지식문을 제거할 수 있다는 점을 유의할 필요가 있습니다. React Wrap Balancer 및 Vercel Analytics repositories에서 <code>&quot;use client&quot;</code>를 포함하도록 esbuild를 구성하는 방법의 예를 찾을 수 있습니다.</li>
</ul>
<h2 id="context">Context</h2>
<p>대부분의 React 애플리케이션은 컴포넌트간에 데이터를 공유하기 위해 <code>context</code>에 의존합니다. <code>context</code>는 <code>createContext</code>를 통해 직접 사용하거나 서드파티 라이브러리의 Provider 컴포넌트를 통해 간접적으로 사용할 수 있습니다.</p>
<p>Next.js 13에서는 클라이언트 컴포넌트에서는 <code>context</code>를 완전히 지원하지만 서버 컴포넌트에서는 <code>context</code>를 생성하거나 사용할 수 없습니다. 서버 컴포넌트는 React state를 가지지 않고(상호작용 X), <code>context</code>는 일부 React state가 업데이트된 후 트리에서 컴포넌트를 다시 렌더링하는 데 주로 사용되기 때문입니다.</p>
<h3 id="클라이언트-컴포넌트에서-context-사용하기">클라이언트 컴포넌트에서 Context 사용하기</h3>
<p>클라이언트 컴포넌트에서는 모든 context API들이 완전히 지원됩니다.</p>
<pre><code class="language-jsx">&#39;use client&#39;

import { createContext, useContext, useState } from &#39;react&#39;

const SidebarContext = createContext()

export function Sidebar() {
  const [isOpen, setIsOpen] = useState()

  return (
    &lt;SidebarContext.Provider value={{ isOpen }}&gt;
      &lt;SidebarNav /&gt;
    &lt;/SidebarContext.Provider&gt;
  )
}

function SidebarNav() {
  let { isOpen } = useContext(SidebarContext)

  return (
    &lt;div&gt;
      &lt;p&gt;Home&lt;/p&gt;

      {isOpen &amp;&amp; &lt;Subnav /&gt;}
    &lt;/div&gt;
  )
}</code></pre>
<p>그러나 <code>Context Provider</code>는 주로 현재 테마와 같은 전역 문제를 공유하기 위해 애플리케이션의 루트 근처에서 렌더링됩니다. 서버 컴포넌트에서 컨텍스트가 지원되지 않기 때문에 애플리케이션의 루트에서 컨텍스트를 만들려고 하면 오류가 발생합니다.</p>
<pre><code class="language-jsx">import { createContext } from &#39;react&#39;

//  createContext is not supported in Server Components
export const ThemeContext = createContext({})

export default function RootLayout({ children }) {
  return (
    &lt;html&gt;
      &lt;body&gt;
        &lt;ThemeContext.Provider value=&quot;dark&quot;&gt;
          {children}
        &lt;/ThemeContext.Provider&gt;
      &lt;/body&gt;
    &lt;/html&gt;
  )
}</code></pre>
<p>따라서, 클라이언트 컴포넌트 안에서 컨텍스트를 만들고 렌더링합니다.</p>
<pre><code class="language-jsx">&#39;use client&#39;

import { createContext } from &#39;react&#39;

export const ThemeContext = createContext({})

export default function ThemeProvider({ children }) {
  return &lt;ThemeContext.Provider value=&quot;dark&quot;&gt;{children}&lt;/ThemeContext.Provider&gt;
}</code></pre>
<p>이제 서버 컴포넌트에서 <code>Provider</code>를 직접 렌더링 할 수 있습니다.</p>
<pre><code class="language-jsx">import ThemeProvider from &#39;./theme-provider&#39;

export default function RootLayout({ children }) {
  return (
    &lt;html&gt;
      &lt;body&gt;
        &lt;ThemeProvider&gt;{children}&lt;/ThemeProvider&gt;
      &lt;/body&gt;
    &lt;/html&gt;
  )
}</code></pre>
<p><code>Provider</code>가 루트에서 렌더링되면 앱 전체의 다른 모든 클라이언트 컴포넌트가 이 컨텍스트를 사용할 수 있습니다.</p>
<h3 id="서버-컴포넌트에서-서드파티-context-provider-렌더링하기">서버 컴포넌트에서 서드파티 Context Provider 렌더링하기</h3>
<p><code>&quot;use client&quot;</code> 지시문이 없는 경우 서버 컴포넌트에서 바로 사용할 수 없기 때문에 클라이언트 컴포넌트로 매핑해서 사용(위 내용과 동일)</p>
<h3 id="서버-컴포넌트간에-데이터-공유하기">서버 컴포넌트간에 데이터 공유하기</h3>
<p>서버 컴포넌트는 대화형이 아니므로 React state를 사용하지 않으므로 데이터를 공유하기 위해 컨텍스트가 필요하지 않습니다. 대신 여러 서버 컴포넌트가 액세스해야 하는 공통 데이터에 대해 네이티브 JavaScript 패턴을 사용할 수 있습니다. 예를 들어 모듈을 사용하여 여러 컴포넌트에서 데이터베이스에 연결해 데이터를 공유할 수 있습니다.</p>
<pre><code class="language-jsx">/* utils/database.js */
export const db = new DatabaseConnection()</code></pre>
<pre><code class="language-jsx">/* app/users/layout.js */
import { db } from &#39;@utils/database&#39;

export async function UsersLayout() {
  let users = await db.query()
  // ...
}</code></pre>
<pre><code class="language-jsx">/* app/users/[id]/page.js */
import { db } from &#39;@utils/database&#39;

export async function DashboardPage() {
  let user = await db.query()
  // ...
}</code></pre>
<p>위의 예에서 <code>layout</code>과 <code>page</code> 모두 데이터베이스 쿼리가 필요합니다. 각 컴포넌트는 <code>@utils/database</code> 모듈을 가져와서 데이터베이스에 대한 액세스를 공유합니다. 이 JavaScript 패턴을 <code>글로벌 싱글톤</code>이라고 합니다.</p>
<h3 id="서버-컴포넌트간에-fetch-요청-공유하기">서버 컴포넌트간에 fetch 요청 공유하기</h3>
<p>데이터를 fetch 할때, 그 결과를 <code>page</code> 또는 <code>layout</code>이나 자식 컴포넌트와 공유할 필요가 있을 수 있습니다. 이는 컴포넌트 간의 불필요한 연결이고, 컴포넌트 간 앞뒤로 <code>props</code> 전달을 하게 만듭니다.</p>
<p>따라서, 데이터를 소비하는 컴포넌트와 함께 데이터 fetch를 공동 배치하는 것이 좋습니다. fetch 요청은 서버 컴포넌트에 자동으로 메모되므로 각 라우트 세그먼트는 중복 요청에 대한 걱정 없이 필요한 데이터를 정확하게 요청할 수 있습니다. Next.js는 fetch 캐시에서 동일한 값을 읽습니다.</p>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs/getting-started/react-essentials">https://nextjs.org/docs/getting-started/react-essentials</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[시작하기 - 프로젝트 구조]]></title>
            <link>https://velog.io/@zen_se/Getting-Started-Project-Structure</link>
            <guid>https://velog.io/@zen_se/Getting-Started-Project-Structure</guid>
            <pubDate>Sat, 22 Jul 2023 10:46:28 GMT</pubDate>
            <description><![CDATA[<h1 id="nextjs-프로젝트-구조">Next.js 프로젝트 구조</h1>
<p>이 페이지에서는 Next.js 프로젝트의 파일 및 폴더 구조에 대한 개요를 제공합니다. 앱 및 페이지 디렉토리 내의 최상위 파일 및 폴더, 구성 파일 및 라우팅 규칙을 다룹니다.</p>
<hr>
<h1 id="최상위-파일">최상위 파일</h1>
<p>next.js 관련</p>
<table>
<thead>
<tr>
<th align="center">파일명</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>next.config.js</code></td>
<td align="center">Next.js 설정 파일</td>
</tr>
<tr>
<td align="center"><code>middleware.ts(.js)</code></td>
<td align="center">미들웨어 정의</td>
</tr>
<tr>
<td align="center"><code>instrumentation.ts</code></td>
<td align="center">OpenTelemetry and Instrumentation</td>
</tr>
<tr>
<td align="center"><code>.env</code></td>
<td align="center">환경변수 파일</td>
</tr>
<tr>
<td align="center"><code>.env.local</code></td>
<td align="center">로컬 환경변수 파일</td>
</tr>
<tr>
<td align="center"><code>.env.production</code></td>
<td align="center">프로덕션 환경변수 파일</td>
</tr>
<tr>
<td align="center"><code>.env.development</code></td>
<td align="center">개발 환경변수 파일</td>
</tr>
<tr>
<td align="center"><code>.next-env.d.ts</code></td>
<td align="center">Next.js용 TypeScript 선언 파일</td>
</tr>
</tbody></table>
<p>Ecosystem</p>
<table>
<thead>
<tr>
<th align="center">파일명</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>package.json</code></td>
<td align="center">프로젝트 의존성 및 스크립트 선언 파일</td>
</tr>
<tr>
<td align="center"><code>.gitignore</code></td>
<td align="center">Git에서 무시할 파일 및 폴더</td>
</tr>
<tr>
<td align="center"><code>tsconfig.json</code></td>
<td align="center">TypeScript용 구성 파일</td>
</tr>
<tr>
<td align="center"><code>jsconfig.json</code></td>
<td align="center">JavaScript용 구성 파일</td>
</tr>
<tr>
<td align="center"><code>.eslintrc.json</code></td>
<td align="center">ESLint용 구성 파일</td>
</tr>
</tbody></table>
<hr>
<h1 id="최상위-폴더">최상위 폴더</h1>
<table>
<thead>
<tr>
<th align="center">폴더 명</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>app</code></td>
<td align="center">앱 라우터</td>
</tr>
<tr>
<td align="center"><code>pages</code></td>
<td align="center">페이지 라우터</td>
</tr>
<tr>
<td align="center"><code>public</code></td>
<td align="center">사용할 정적 에셋(글꼴, 이미지 등)</td>
</tr>
<tr>
<td align="center"><code>src</code></td>
<td align="center">추가적인 애플리케이션 소스 폴더</td>
</tr>
</tbody></table>
<hr>
<h1 id="app-routing-컨벤션">App Routing 컨벤션</h1>
<h2 id="routing-파일">Routing 파일</h2>
<table>
<thead>
<tr>
<th align="center">파일명</th>
<th align="center">확장자</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>layout</code></td>
<td align="center"><code>.js</code> <code>.jsx</code> <code>.tsx</code></td>
<td align="center">레이아웃</td>
</tr>
<tr>
<td align="center"><code>page</code></td>
<td align="center"><code>.js</code> <code>.jsx</code> <code>.tsx</code></td>
<td align="center">페이지</td>
</tr>
<tr>
<td align="center"><code>loading</code></td>
<td align="center"><code>.js</code> <code>.jsx</code> <code>.tsx</code></td>
<td align="center">로딩 UI</td>
</tr>
<tr>
<td align="center"><code>not-found</code></td>
<td align="center"><code>.js</code> <code>.jsx</code> <code>.tsx</code></td>
<td align="center">Not found UI</td>
</tr>
<tr>
<td align="center"><code>error</code></td>
<td align="center"><code>.js</code> <code>.jsx</code> <code>.tsx</code></td>
<td align="center">Error UI</td>
</tr>
<tr>
<td align="center"><code>global-error</code></td>
<td align="center"><code>.js .jsx .tsx</code></td>
<td align="center">Global error UI</td>
</tr>
<tr>
<td align="center"><code>route</code></td>
<td align="center"><code>.js .ts</code></td>
<td align="center">API 엔드포인트</td>
</tr>
<tr>
<td align="center"><code>template</code></td>
<td align="center"><code>.js .jsx .tsx</code></td>
<td align="center">Re-rendered layout</td>
</tr>
<tr>
<td align="center"><code>default</code></td>
<td align="center"><code>.js .jsx .tsx</code></td>
<td align="center">병렬 라우팅 대체 페이지</td>
</tr>
</tbody></table>
<h2 id="중첩-라우트">중첩 라우트</h2>
<table>
<thead>
<tr>
<th align="center">파일명</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>folder</code></td>
<td align="center">라우트 segment</td>
</tr>
<tr>
<td align="center"><code>folder/folder</code></td>
<td align="center">중첩된 라우트 segment</td>
</tr>
</tbody></table>
<h2 id="동적-라우트">동적 라우트</h2>
<table>
<thead>
<tr>
<th align="center">파일명</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>[folder]</code></td>
<td align="center">동적 라우트 segment</td>
</tr>
<tr>
<td align="center"><code>[...folder]</code></td>
<td align="center">Catch-all segments</td>
</tr>
<tr>
<td align="center"><code>[[...folder]]</code></td>
<td align="center">Optional catch-all segments</td>
</tr>
</tbody></table>
<h2 id="route-groups-and-private-folders">Route Groups and Private Folders</h2>
<table>
<thead>
<tr>
<th align="center">파일명</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>(folder)</code></td>
<td align="center">Group routes without affecting routing</td>
</tr>
<tr>
<td align="center"><code>_folder</code></td>
<td align="center">Opt folder and all child segments out of routing</td>
</tr>
</tbody></table>
<h2 id="parallel-and-intercepted-routes">Parallel and Intercepted Routes</h2>
<table>
<thead>
<tr>
<th align="center">파일명</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>@folder</code></td>
<td align="center">Named slot</td>
</tr>
<tr>
<td align="center"><code>(.)folder</code></td>
<td align="center">Intercept same level</td>
</tr>
<tr>
<td align="center"><code>(..)folder</code></td>
<td align="center">Intercept one level above</td>
</tr>
<tr>
<td align="center"><code>(..)(..)folder</code></td>
<td align="center">Intercept two levels above</td>
</tr>
<tr>
<td align="center"><code>(...)folder</code></td>
<td align="center">Intercept from root</td>
</tr>
</tbody></table>
<h2 id="metadata-file-conventions">Metadata File Conventions</h2>
<h3 id="app-icons">App Icons</h3>
<table>
<thead>
<tr>
<th align="center">파일명</th>
<th align="center">확장자</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>favicon</code></td>
<td align="center"><code>.ico</code></td>
<td align="center">Favicon file</td>
</tr>
<tr>
<td align="center"><code>icon</code></td>
<td align="center"><code>.ico .jpg .jpeg .png .svg</code></td>
<td align="center">App Icon file</td>
</tr>
<tr>
<td align="center"><code>icon</code></td>
<td align="center"><code>.js .ts .tsx</code></td>
<td align="center">Generated App Icon</td>
</tr>
<tr>
<td align="center"><code>apple-icon</code></td>
<td align="center"><code>.jpg .jpeg, .png</code></td>
<td align="center">Apple App Icon file</td>
</tr>
<tr>
<td align="center"><code>apple-icon</code></td>
<td align="center"><code>.js .ts .tsx</code></td>
<td align="center">Generated Apple App Icon</td>
</tr>
</tbody></table>
<h3 id="open-graph-and-twitter-images">Open Graph and Twitter Images</h3>
<table>
<thead>
<tr>
<th align="center">파일명</th>
<th align="center">확장자</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>opengraph-image</code></td>
<td align="center"><code>.jpg .jpeg .png .gif</code></td>
<td align="center">Open Graph image file</td>
</tr>
<tr>
<td align="center"><code>opengraph-image</code></td>
<td align="center"><code>.js .ts .tsx</code></td>
<td align="center">Generated Open Graph image</td>
</tr>
<tr>
<td align="center"><code>twitter-image</code></td>
<td align="center"><code>.jpg .jpeg .png .gif</code></td>
<td align="center">Twitter image file</td>
</tr>
<tr>
<td align="center"><code>twitter-image</code></td>
<td align="center"><code>.js .ts .tsx</code></td>
<td align="center">Generated Twitter image</td>
</tr>
</tbody></table>
<h3 id="seo">SEO</h3>
<table>
<thead>
<tr>
<th align="center">파일명</th>
<th align="center">확장자</th>
<th align="center">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center"><code>sitemap</code></td>
<td align="center"><code>.xml</code></td>
<td align="center">Sitemap file</td>
</tr>
<tr>
<td align="center"><code>sitemap</code></td>
<td align="center"><code>.js .ts</code></td>
<td align="center">Generated Sitemap</td>
</tr>
<tr>
<td align="center"><code>robots</code></td>
<td align="center"><code>.txt</code></td>
<td align="center">Robots file</td>
</tr>
<tr>
<td align="center"><code>robots</code></td>
<td align="center"><code>.js .ts</code></td>
<td align="center">Generated Robots file</td>
</tr>
</tbody></table>
<hr>
<h1 id="page-routing-컨벤션">Page Routing 컨벤션</h1>
<p>(생략)</p>
<hr>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs/getting-started/project-structure">https://nextjs.org/docs/getting-started/project-structure</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[시작하기 - 설치]]></title>
            <link>https://velog.io/@zen_se/Getting-Started-Installation</link>
            <guid>https://velog.io/@zen_se/Getting-Started-Installation</guid>
            <pubDate>Sat, 22 Jul 2023 09:35:17 GMT</pubDate>
            <description><![CDATA[<h1 id="설치">설치</h1>
<p>시스템 요구사양:</p>
<ul>
<li>Node.js 16.8 이상</li>
<li>macOS, Windows(WSL 포함), Linux 지원</li>
</ul>
<hr>
<h1 id="자동-설치">자동 설치</h1>
<p>모든 것을 자동으로 설정해주는 <code>create-next-app</code>을 사용하여 새로운 Next.js 앱을 만드는 것이 좋습니다. 프로젝트를 만들려면 다음을 실행합니다.</p>
<pre><code>npx create-next-app@latest</code></pre><p>설치 시 다음 프롬프트가 표시됩니다.</p>
<pre><code>What is your project named? my-app
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like to use `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to customize the default import alias? No / Yes</code></pre><p>Next.js는 이제 기본적으로 <code>TypeScript</code>, <code>ESLint</code> 및 <code>Tailwind CSS</code> 구성과 함께 제공됩니다. 애플리케이션 코드에 <code>src</code> 디렉토리를 사용하도록 선택할 수도 있습니다.</p>
<p>모든 선택을 마치면 <code>create-next-app</code> 은 프로젝트 이름으로 폴더를 생성하고 필요한 종속 항목을 설치합니다.</p>
<blockquote>
<ul>
<li>참고 : 새 프로젝트에서 <code>Page Router</code>를 사용할 수 있습니다. 그러나 React의 최신 기능을 활용하려면 <code>App Router</code>를 사용하는 것이 좋습니다.</li>
</ul>
</blockquote>
<hr>
<h1 id="수동-설치">수동 설치</h1>
<p>Next.js 애플리케이션을 직접 생성하려면, 필요한 패키지를 설치해야합니다.</p>
<pre><code>npm install next@latest react@latest react-dom@latest</code></pre><p><code>pakage.json</code>파일을 열어 <code>scripts</code>을 추가합니다.</p>
<pre><code class="language-json">{
  &quot;scripts&quot;: {
    &quot;dev&quot;: &quot;next dev&quot;,
    &quot;build&quot;: &quot;next build&quot;,
    &quot;start&quot;: &quot;next start&quot;,
    &quot;lint&quot;: &quot;next lint&quot;
  }
}</code></pre>
<p>이러한 스크립트는 애플리케이션 개발의 단계를 나타냅니다.</p>
<ul>
<li><p><code>dev</code>: <code>next dev</code>를 실행하여 개발 모드에서 Next.js를 시작합니다.</p>
</li>
<li><p><code>build</code> : <code>next build</code>를 실행하여 프로덕션 용도로 애플리케이션을 빌드합니다. </p>
</li>
<li><p><code>start</code> : <code>next start</code>를 실행하여 Next.js 프로덕션 서버를 시작합니다.</p>
</li>
<li><p><code>lint</code>: <code>next lint</code>를 실행하여 Next.js의 내장 ESLint 구성을 설정합니다.</p>
</li>
</ul>
<h2 id="디렉토리-만들기">디렉토리 만들기</h2>
<p>Next.js는 파일 시스템 라우팅을 사용합니다. 즉, 파일의 구조가 애플리케이션의 경로를 결정합니다.</p>
<h3 id="app-디렉토리">app 디렉토리</h3>
<p>새로운 애플리케이션의 경우 <code>App Router</code>를 사용하는 것이 좋습니다.
<code>App Router</code>는 <code>Page Router</code>의 진화된 버전이며, React의 최신 기능을 사용할 수 있습니다.</p>
<p><code>App Router</code>를 사용하려면 <code>app/</code> 폴더를 만든 다음 <code>layout.jsx</code> 및 <code>page.jsx</code> 파일을 추가합니다. 사용자가 애플리케이션의 루트(<code>/</code>)를 방문할 때 렌더링됩니다.
<img src="https://velog.velcdn.com/images/zen_se/post/99a0aae7-277c-4a2f-b7c6-1230ebdfa1a0/image.png" alt=""></p>
<p><code>app/layout.jsx</code> 파일에 <code>&lt;html&gt;</code>태그와 <code>&lt;body&gt;</code>태그로 루트 레이아웃을 만듭니다.</p>
<pre><code class="language-jsx">export default function RootLayout({ children }) {
  return (
    &lt;html lang=&quot;en&quot;&gt;
      &lt;body&gt;{children}&lt;/body&gt;
    &lt;/html&gt;
  )
}</code></pre>
<p>마지막으로 홈페이지 <code>app/page.jsx</code>를 만듭니다.</p>
<pre><code class="language-jsx">export default function Page() {
  return &lt;h1&gt;Hello, Next.js!&lt;/h1&gt;
}</code></pre>
<blockquote>
<p>참고 : <code>layout.jsx</code>를 만드는 것을 잊은 경우 <code>next dev</code>로 개발 서버를 실행할 때 Next.js가 자동으로 파일을 생성해줍니다.</p>
</blockquote>
<h3 id="page-디렉토리선택사항">page 디렉토리(선택사항)</h3>
<p><code>Page Router</code>를 사용하려는 경우.
(생략)</p>
<h2 id="public-디렉토리선택-사항">public 디렉토리(선택 사항)</h2>
<p>선택적으로 공용 폴더를 생성하여 이미지, 글꼴 등과 같은 정적 어셋을 저장할 수 있습니다. 그러면 기본 URL(/)에서 시작하는 코드에서 <code>public</code> 디렉터리 내의 파일을 참조할 수 있습니다.</p>
<hr>
<h1 id="개발서버-실행하기">개발서버 실행하기</h1>
<ol>
<li><code>npm run dev</code>를 실행하여 개발 서버를 시작합니다.</li>
<li><code>http://localhost:3000</code>로 방문해서 애플리케이션을 볼 수 있습니다.</li>
<li><code>app/layout.jsx</code> 파일을 편집하고 저장하면 브라우저에서 업데이트된 결과를 볼 수 있습니다.</li>
</ol>
<hr>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs/getting-started/installation">https://nextjs.org/docs/getting-started/installation</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[시작하기 - 소개]]></title>
            <link>https://velog.io/@zen_se/Getting-Started-Introduction</link>
            <guid>https://velog.io/@zen_se/Getting-Started-Introduction</guid>
            <pubDate>Sat, 22 Jul 2023 08:39:05 GMT</pubDate>
            <description><![CDATA[<h1 id="소개">소개</h1>
<p> Next.js 공식문서에 오신것을 환영합니다.</p>
<hr>
<h1 id="nextjs가-무엇인가요">Next.js가 무엇인가요?</h1>
<p>Next.js는 웹 애플리케이션을 구축하기 위한 프레임워크입니다.</p>
<p>Next.js를 사용하면 React 컴포넌트를 사용하여 UI를 구축할 수 있습니다. 그리고 Next.js는 애플리케이션을 위한 추가적인 구조, 기능, 최적화를 제공합니다.</p>
<p>또한 내부적으로 Next.js는 번들링, 컴파일 등과 같은 도구를 추상화하고 자동으로 구성합니다. 이를 통해 도구 설정에 시간을 소비하는 대신 애플리케이션 구현에 집중할 수 있습니다.</p>
<p>1인 개발자이든 대규모 팀의 일원이든 관계없이 Next.js는 상호작용 가능하며 동적인 빠른 웹 애플리케이션을 구축하는 데 도움이 될 수 있습니다.</p>
<hr>
<h1 id="주요-기능">주요 기능</h1>
<p>Next.js의 주요한 기능 중 일부는 다음과 같습니다.</p>
<ul>
<li><p><code>Routing</code> : 레이아웃, 중첩 라우팅, 로드 상태, 오류 처리 등을 지원하는 서버 컴포넌트 위에 구축된 파일 시스템 기반 라우터입니다.</p>
</li>
<li><p><code>Rendering</code> : 클라이언트 및 서버 컴포넌트를 사용한 <code>CSR</code>과 <code>SSR</code>이 있습니다. 서버에서 정적 및 동적 렌더링으로 더욱 최적화되었습니다. Edge와 Node.js 런타임에 스트리밍됩니다.</p>
</li>
<li><p><code>Data Fetching</code> : React 컴포넌트의 <code>async/await</code>와 React와 웹 플랫폼에 일치하는 <code>fetch()</code> API로 간소화된 데이터를 가져옵니다.</p>
</li>
<li><p><code>Styling</code> : <code>CSS 모듈</code>, <code>Tailwind CSS</code> 및 <code>CSS-in-JS</code> 등 여러 스타일링 방법을 지원합니다.</p>
</li>
<li><p><code>Optimization</code> : 애플리케이션의 성능과 사용자 경험을 개선하기 위한 이미지, 글꼴 및 스크립트를 최적화합니다.</p>
</li>
<li><p><code>TypeScript</code> : TypeScript에 대한 지원이 개선되어 더 나은 타입 검사와 효율적인 컴파일, 사용자 지정 TypeScript 플러그인과 타입 검사를 제공합니다.</p>
</li>
<li><p><code>API Reference</code> : Next.js의 API 디자인이 업데이트되었습니다. 새로운 API는 API Reference 섹션을 참조하세요.</p>
</li>
</ul>
<hr>
<h1 id="공식문서-사용법">공식문서 사용법</h1>
<p>공식문서의 섹션과 페이지는 기본에서 고급까지 순차적으로 구성되어 있으므로 Next.js 애플리케이션을 빌드할 때 단계별로 따라할 수 있습니다. 그러나 순서에 관계없이 읽거나 사용 사례에 적용되는 페이지로 건너뛸 수 있습니다.</p>
<p>사이드바 상단에는 <code>앱 라우터</code>와 <code>페이지 라우터</code> 로 전환할 수 있는 드롭다운 메뉴가 있습니다. 각 라우터의 고유한 기능이 있으므로 어떤 탭이 선택되어 있는지 확인해야합니다.</p>
<p>페이지 오른쪽에는 페이지 섹션 사이를 쉽게 탐색할 수 있는 목차가 표시됩니다. 페이지 상단의 이동 경로는 App Router 문서 또는 Pages Router 문서를 보고 있는지 여부도 나타냅니다.</p>
<p>시작하려면 설치 섹션을 확인하세요. <code>React</code> 또는 <code>Server Components</code>를 처음 사용하는 경우 React Essentials 페이지를 읽는 것이 좋습니다.</p>
<hr>
<h1 id="사전-지식">사전 지식</h1>
<p>문서는 초보자에게 친숙하도록 설계되었지만 문서가 Next.js 기능에 집중할 수 있도록 기준선을 설정해야 합니다. 새로운 개념을 도입할 때마다 관련 문서에 대한 링크를 제공할 것입니다.</p>
<p>문서를 최대한 활용하려면 HTML, CSS 및 React에 대한 기본적인 이해가 있는 것이 좋습니다. React 기술을 학습해야 하는 경우 다음 링크를 확인하세요.</p>
<ul>
<li><a href="https://react.dev/learn">React: Official React Documentation</a></li>
<li><a href="https://nextjs.org/docs/getting-started/react-essentials">React Essentials</a></li>
</ul>
<hr>
<blockquote>
<p>원문 - <a href="https://nextjs.org/docs">https://nextjs.org/docs</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[CDN과 Edge]]></title>
            <link>https://velog.io/@zen_se/CDN%EA%B3%BC-Edge</link>
            <guid>https://velog.io/@zen_se/CDN%EA%B3%BC-Edge</guid>
            <pubDate>Mon, 17 Jul 2023 08:42:39 GMT</pubDate>
            <description><![CDATA[<h2 id="네트워크란">네트워크란?</h2>
<p>애플리케이션 코드가 저장되고 네트워크에 배포된 후 실행되는 위치를 아는 것은 도움이 됩니다. 네트워크는 리소스를 공유할 수 있는 연결된 컴퓨터(또는 서버)라고 생각할 수 있습니다.
Next.js 애플리케이션의 경우 애플리케이션 코드를 원본 서버, CDN(Content Delivery Network) 및 Edge에 배포할 수 있습니다. 각각이 무엇인지 살펴보겠습니다.</p>
<h2 id="origin-server-원본-서버">Origin Server (원본 서버)</h2>
<p>앞서 설명한 것처럼 서버는 애플리케이션 코드의 원래 버전을 저장하고 실행하는 주 컴퓨터를 가리킵니다.
CDN 서버 및 Edge 서버와 같이 어플리케이션 코드가 배포될 수 있는 다른 위치와 이 서버를 구별하기 위해 <code>origin</code>이라는 용어를 사용합니다.
원본 서버가 요청을 받으면 응답을 보내기 전에 일부 계산을 수행합니다. 이 계산 작업의 결과는 CDN(Content Delivery Network)으로 이동할 수 있습니다.</p>
<h2 id="cdn-콘텐츠-전송-네트워크">CDN (콘텐츠 전송 네트워크)</h2>
<p>CDN은 전 세계 여러 위치에 정적 콘텐츠(예: HTML 및 이미지 파일)를 저장하고 클라이언트와 원본 서버 사이에 배치됩니다. 새로운 요청이 들어오면 사용자와 가장 가까운 위치의 CDN에서 캐시된 결과를 응답으로 보냅니다.</p>
<p><img src="https://velog.velcdn.com/images/zen_se/post/d7d317bf-e447-4184-9895-d6c677cdae67/image.png" alt=""></p>
<p>이렇게 하면 오리진에서 각 요청에 대한 계산을 모두 할 필요가 없기 때문에 오리진의 부하가 줄어듭니다. 또한 사용자에게 지리적으로 더 가까운 위치에서 응답이 오기 때문에 사용자가 더 빠르게 응답을 받을 수 있습니다.</p>
<p>Next.js에서 사전 렌더링을 미리 수행할 수 있고, CDN은 사전 렌더링의 정적 결과를 저장하는 데 적합하기 때문에 콘텐츠 전달 속도가 빨라집니다.</p>
<h2 id="the-edge">The Edge</h2>
<p>Edge는 사용자에게 가장 가까운 네트워크 주변부(또는 가장자리)에 대한 일반화된 개념입니다. CDN도 네트워크의 가장자리에 정적 콘텐츠를 저장하기 때문에 Edge의 일부로 간주될 수 있습니다.</p>
<p>CDN과 유사하게 Edge 서버는 전 세계 여러 위치에 배포됩니다. 그러나 정적 콘텐츠를 저장하는 CDN과 달리 일부 Edge 서버는 작은 코드 조각을 실행할 수 있습니다.
이는 캐싱과 코드 실행 모두 사용자에게 더 가까운 Edge에서 수행할 수 있음을 의미합니다.</p>
<p>전통적으로 클라이언트 측 또는 서버 측에서 수행되었던 일부 작업을 Edge로 이동하면 클라이언트로 전송되는 코드의 양이 줄어들고 사용자 요청의 일부가 원본 서버로 다시 돌아갈 필요가 없기 때문에 대기시간이 감소하고 애플리케이션의 성능을 높일 수 있습니다.
<a href="https://vercel.com/features/edge-functions#:~:text=Unlock%20the%20potential%20of%20edge%20computing">여기</a>에서 Next.js를 사용한 Edge 예제를 참조하세요.</p>
<p>Next.js에서는 미들웨어를 사용하여 Edge에서 코드를 실행할 수 있으며 곧 React Server 컴포넌트도 실행 가능할 것입니다.</p>
<blockquote>
<p>원문 - <a href="https://nextjs.org/learn/foundations/how-nextjs-works/cdns-and-edge">https://nextjs.org/learn/foundations/how-nextjs-works/cdns-and-edge</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[렌더링(Rendering)]]></title>
            <link>https://velog.io/@zen_se/Rendering</link>
            <guid>https://velog.io/@zen_se/Rendering</guid>
            <pubDate>Mon, 17 Jul 2023 07:35:46 GMT</pubDate>
            <description><![CDATA[<h2 id="rendering이란">Rendering이란?</h2>
<p>React로 작성된 코드를 UI를 표현하는 HTML로 변환하기 위해서는 피할 수 없는 프로세스가 있습니다. 이 프로세스를 <code>rendering(렌더링)</code>이라고 합니다.</p>
<p>렌더링은 서버에서도 클라이언트에서도 일어날 수 있습니다.
빌드타임에 미리 일어날 수도 있고, 런타임에 모든 요청에 대해 일어날 수 있습니다.</p>
<p>Next.js를 사용하면 <code>서버측 렌더링(Server-Side Rendering)</code>, <code>정적 사이트 생성(Static Site Generation)</code> 및 <code>클라이언트측 렌더링(Client-Side Rendering)</code>의 세 가지 유형의 렌더링 방법을 사용할 수 있습니다.</p>
<h2 id="pre-rendering">Pre-Rendering</h2>
<p><code>Server-Side Rendering</code>과 <code>Static Site Generation</code>은 페이지가 클라이언트로 전송되기 전에 외부 데이터를 가져오고 React 구성 요소를 HTML로 변환하기 때문에 <code>사전 렌더링(Pre-Rendering)</code>이라고도 합니다.</p>
<h2 id="client-side-renderingcsr-vs-pre-rendering">Client-Side Rendering(CSR) vs. Pre-Rendering</h2>
<p>일반적인 React 어플리케이션에서 브라우저는 서버에서 비어있는 HTML 껍데기를 UI를 구성하기 위한 JavaScript 파일과 함께 받습니다. 이처럼 첫 렌더링이 사용자의 기기에서 일어나기 때문에 <code>Clinet-Side Rendering</code>이라고 합니다.</p>
<p><img src="https://velog.velcdn.com/images/zen_se/post/c4527d5a-fef7-42ab-a0fd-bebb765def27/image.png" alt=""></p>
<blockquote>
<p>참고: React의 useEffect 또는 useSWR과 같은 data fetching hook를 사용하여 데이터를 가져오도록 선택하여 Next.js 애플리케이션의 특정 컴포넌트에 대해 Client-Side Rendering을 사용하도록 선택할 수 있습니다.</p>
</blockquote>
<p>반대로, Next.js는 기본적으로 모든 페이지를 <code>Pre-Rendering</code>합니다. 즉, 사용자 기기에서 JavaScript로 모든 작업을 수행하는 대신 HTML이 서버에서 미리 생성됨을 의미합니다.</p>
<p>실제로 100% Client-Side Rendering인 앱의 경우, 사용자는 렌더링 작업이 수행되는 동안 빈 페이지를 보게됩니다. 그러나 사전 렌더링에서는 사용자가 처음부터 구성된 HTML을 볼 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/zen_se/post/cd6067de-3153-4134-ae75-289b8626103e/image.png" alt=""></p>
<p>이제 두가지 타입의 사전 렌더링에 대해 살펴보겠습니다.</p>
<h2 id="server-side-renderingssr">Server-Side Rendering(SSR)</h2>
<p><code>Server-Side Rendering</code>을 사용하면 페이지의 HTML은 각 요청에 대해 서버에서 생성됩니다. 그런 다음 생성된 HTML, JSON 데이터 및 페이지를 대화형으로 만들기 위한 JavaScript 파일이 서버에서 클라이언트로 전송됩니다.</p>
<p>클라이언트에서 HTML은 빠른 비대화형 페이지를 표시하는데 사용되고, React는 JSON 데이터 및 JavaScript 명령을 사용하여 구성 요소를 대화형으로 만듭니다(예: 버튼에 이벤트 핸들러 달기). 이 과정을 <code>hydration(수화)</code>라고합니다.</p>
<p>Next.js에서는 <code>getServerSideProps</code>를 사용하여 페이지를 Server-Side Rendering 되도록 선택할 수 있습니다. - <a href="https://nextjs.org/docs/basic-features/data-fetching/get-server-side-props">getServerSideProps 문서</a></p>
<blockquote>
<p>참고: React 18 및 Next 12에는 <code>React 서버 컴포넌트</code>의 알파 버전이 도입되었습니다. 서버 컴포넌트는 서버에서 완전히 렌더링되며 렌더링을 위해 클라이언트 측 JavaScript가 필요하지 않습니다. 또한 서버 컴포넌트를 사용하면 개발자가 일부 로직을 서버에 유지하고 해당 로직의 결과만 클라이언트에 보낼 수 있습니다. 이렇게 하면 클라이언트로 전송되는 번들 크기가 줄어들고 클라이언트 측 렌더링 성능이 향상됩니다.</p>
</blockquote>
<h2 id="static-site-generationssg">Static Site Generation(SSG)</h2>
<p><code>Static Site Generation</code>을 사용하면 HTML이 서버에서 생성되지만, <code>Server-Side Rendering</code>과는 다르게 런타임에 서버를 사용하지 않습니다. 대신 페이지는 빌드타임 시 애플리케이션이 배포될 때 한 번 생성되며 HTML은 CDN에 저장되고 각 요청때마다 재사용됩니다.</p>
<p>Next.js에서 getStaticProps를 사용하여 페이지를 정적으로 생성하도록 선택할 수 있습니다. - <a href="https://nextjs.org/docs/basic-features/data-fetching/get-static-props">getStaticProps 문서</a></p>
<blockquote>
<p>참고: <code>증분 정적 재생성(Incremental Static Regeneration)</code>을 사용하면 사이트를 빌드한 후에도 정적 페이지를 생성하거나 업데이트할 수 있습니다. 즉, 데이터가 변경되더라도 전체 사이트를 다시 빌드할 필요가 없습니다. - <a href="https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration">Incremental Static Regeneration 문서</a></p>
</blockquote>
<p>Next.js의 장점은 SSG, SSR, CSR 등 페이지별로 가장 적합한 렌더링 방식을 선택할 수 있다는 것입니다. 특정 상황에 적합한 렌더링 방법에 대해 자세히 알아보려면 data fetching 문서를 참조하세요. - <a href="https://nextjs.org/docs/basic-features/data-fetching/overview">data fetching 문서</a></p>
<p>다음 섹션에서는 배포 후 코드를 저장하거나 실행할 수 있는 위치에 대해 설명합니다.</p>
<blockquote>
<p>원문 - <a href="https://nextjs.org/learn/foundations/how-nextjs-works/rendering">https://nextjs.org/learn/foundations/how-nextjs-works/rendering</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Client and Server]]></title>
            <link>https://velog.io/@zen_se/Client-and-Server</link>
            <guid>https://velog.io/@zen_se/Client-and-Server</guid>
            <pubDate>Mon, 17 Jul 2023 05:57:22 GMT</pubDate>
            <description><![CDATA[<h2 id="클라이언트와-서버">클라이언트와 서버</h2>
<p>웹 어플리케이션에서 클라이언트는 어플리케이션 코드에 대한 요청을 서버에 보내는 사용자 기기의 브라우저를 의미합니다.
그런 다음 서버에서 받은 응답을 사용자가 상호 작용할 수 있는 인터페이스로 바꿉니다.</p>
<p><img src="https://velog.velcdn.com/images/zen_se/post/da155266-8abc-4b93-9b70-e6fcf8eb673e/image.png" alt=""></p>
<p>서버는 애플리케이션 코드를 저장하고, 클라이언트로부터 요청을 받고, 일부 계산을 수행하고, 적절한 응답을 다시 보내는 데이터 센터의 컴퓨터를 말합니다.</p>
<blockquote>
<p>원문 - <a href="https://nextjs.org/learn/foundations/how-nextjs-works/client-and-server">https://nextjs.org/learn/foundations/how-nextjs-works/client-and-server</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Build Time vs. Runtime]]></title>
            <link>https://velog.io/@zen_se/Build-Time-vs.-Runtime</link>
            <guid>https://velog.io/@zen_se/Build-Time-vs.-Runtime</guid>
            <pubDate>Mon, 10 Jul 2023 11:11:42 GMT</pubDate>
            <description><![CDATA[<h2 id="build-time과-runtime">Build Time과 Runtime</h2>
<p>빌드 시간(또는 빌드 단계)은 프로덕션을 위해 애플리케이션 코드를 준비하는 일련의 단계의 이름입니다.</p>
<p>애플리케이션을 빌드할 때 Next.js는 코드를 서버에 배포하고 사용자가 사용할 준비가 된 프로덕션 최적화 파일로 변환합니다. 이러한 파일에는 다음이 포함됩니다.</p>
<blockquote>
</blockquote>
<ul>
<li>정적으로 생성된 페이지의 HTML 파일</li>
<li>서버에서 페이지를 렌더링하기 위한 JavaScript 코드</li>
<li>클라이언트에서 상호작용 가능한 페이지를 위한 JavaScript 코드</li>
<li>CSS 파일</li>
</ul>
<p>런타임(또는 요청 시간)은 애플리케이션이 빌드 및 배포된 후 사용자 요청에 대한 응답으로 애플리케이션이 실행되는 기간을 의미합니다.</p>
<p>다음 섹션에서 클라이언트, 서버 및 렌더링과 같이 이 섹션에서 소개한 몇 가지 용어에 대해 설명하겠습니다.</p>
<blockquote>
<p>원문 - <a href="https://nextjs.org/learn/foundations/how-nextjs-works/buildtime-and-runtime">https://nextjs.org/learn/foundations/how-nextjs-works/buildtime-and-runtime</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Code Splitting]]></title>
            <link>https://velog.io/@zen_se/Code-Splitting</link>
            <guid>https://velog.io/@zen_se/Code-Splitting</guid>
            <pubDate>Mon, 10 Jul 2023 11:00:57 GMT</pubDate>
            <description><![CDATA[<h2 id="code-splitting이란">Code Splitting이란?</h2>
<p>개발자는 일반적으로 애플리케이션을 서로 다른 URL에서 액세스할 수 있는 여러 페이지로 분할합니다. 이러한 각 페이지는 애플리케이션에 대한 고유한 진입점(entry point)이 됩니다.</p>
<p>Code Splitting은 애플리케이션의 번들을 각 진입점에 필요한 더 작은 덩어리(chunk)로 분할하는 과정입니다. 이 과정의 목표는 해당 페이지를 실행하는 데 필요한 코드만 로드하여 애플리케이션의 초기 로드 시간을 개선하는 것입니다.
<img src="https://velog.velcdn.com/images/zen_se/post/b37d5580-6638-41c1-8258-c426d1037b51/image.png" alt=""></p>
<p>Next.js에는 코드 분할 기능이 내장되어 있습니다. <code>pages/</code> 디렉토리 내의 각 파일은 빌드 단계에서 자체 JavaScript 번들로 자동으로 코드 분할됩니다.</p>
<p>또한,</p>
<ul>
<li>페이지 간에 공유되는 모든 코드는 이후 탐색에서 동일한 코드를 다시 다운로드하지 않도록 다른 번들로 분할됩니다.</li>
<li>초기 페이지 로드 후 Next.js는 사용자가 탐색할 가능성이 있는 다른 페이지의 코드를 미리 로드할 수 있습니다.</li>
<li>Dynamic import는 처음에 로드된 코드를 수동으로 분할하는 또 다른 방법입니다.</li>
</ul>
<blockquote>
<p>원문 - <a href="https://nextjs.org/learn/foundations/how-nextjs-works/code-splitting">https://nextjs.org/learn/foundations/how-nextjs-works/code-splitting</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Bundling]]></title>
            <link>https://velog.io/@zen_se/Bundling</link>
            <guid>https://velog.io/@zen_se/Bundling</guid>
            <pubDate>Mon, 10 Jul 2023 10:43:06 GMT</pubDate>
            <description><![CDATA[<h2 id="bundling이란">Bundling이란?</h2>
<p>개발자는 애플리케이션을 더 큰 애플리케이션을 구축하는 데 사용할 수 있는 모듈, 컴포넌트 및 함수로 나눕니다. 이러한 내부 모듈과 외부 패키지의 export와 import가 복잡한 파일 종속성을 가진 웹을 만듭니다.</p>
<p><img src="https://velog.velcdn.com/images/zen_se/post/ecd7f6ff-6c7a-4da9-9d18-455d3cc6d4bf/image.png" alt=""></p>
<p>Bundling은 사용자가 웹 페이지를 방문할 때 파일에 대한 요청 수를 줄이기 위해 웹의 종속성(Dependency)을 해결하고 파일(또는 모듈)을 브라우저에 최적화된 번들로 병합(또는 &#39;패키징&#39;)하는 프로세스입니다.</p>
<blockquote>
<p>원문 - <a href="https://nextjs.org/learn/foundations/how-nextjs-works/bundling">https://nextjs.org/learn/foundations/how-nextjs-works/bundling</a></p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>