NEXT

TIL | Next.js 13 간단 정리

얼마전, vercel에서 Nextjs ver13 관련 컨퍼런스를 진행하였다. 해당 컨퍼런스를 보고 블로그 및 문서들을 참고하여 어떠한 내용이 추가되었는지 정리해보았다.

Install

npx create-next-app@latest --experimental-app 

시작하기 앞서, nextjs의 최신 버전을 설치하게 되면, 위와 같은 구조로 설치가 된다. 이전과 다르게 app 폴더가 생겼으며 tsxdefault로 설치가 된다.



Router

가장 큰 특징중 하나로는 라우팅 구조이다. 기존에는 page 폴더에서 페이지 라우팅 컴포넌트만 선언하고 다른 폴더에서 관련 컴포넌트를 주입해 사용했던 구조였지만, 페이지 라우팅 컴포넌트 이외 컴포넌트들도 선언 및 활용이 가능할 수 있는 app 폴더가 생겼다. 이로 인해 하나의 폴더에서의 관련 소스들의 관리가 용이해졌다. (13 버전으로 업데이트시, app 폴더를 사용하지 않고 page 폴더를 통해서 라우팅도 여전히 가능하다.) 또한 라우팅 컴포넌트인 page 이외 다른 역할들의 컴포넌트들을 제공하는데 이는 다음과 같다.

  • layout(optional, only required for app root): 해당 레이어 이하의 페이지마다 공통적으로 보여줄 UI를 정의하는데 사용되며 UI 및 상태값 공유 가능 (root layout의 경우, 기존에 존재하던 _app.tsx, _document.tsx 파일을 대체)

  • page(required): 라우팅에 해당하는 UI들을 보여주기 위한 파일이다.

  • template(optional): layout과 비슷하지만, 상태를 공유하지 않고 네비게이션 이동시 새로운 컴포넌트가 마운팅이 된다. (단순하게 UI만 공유하고자 할 경우 사용)

  • loading(optional): 앱의 로딩 UI를 나타낼때 사용되는 컴포넌트이며, 페이지를 React Suspense Boundary로 자동 래핑한다. (추가 config 없이 자동으로 로딩 UI를 보여줌)

  • error(optional): 앱의 에러 UI를 나타낼때 사용되는 컴포넌트이며, 페이지를 React Error Boundary로 자동 래핑한다. (추가 config 없이 자동으로 에러 UI를 보여줌)



Server Components

app 폴더는 리액트의 서버 컴포넌트 아키텍쳐를 지원한다. 간단하게 말하자면, app 이하의 컴포넌트들은 기본적으로 서버 컴포넌트로서 제공되며, 상단의 "use client" 선언을 통해 CSR 컴포넌트로 사용할 수 있다. (여기서 말하는 서버 컴포넌트는, 기존에 존재하는 SSR과 다른 방식이다.)

서버 컴포넌트: 서버에서만 동작하며 앱 규모가 커짐에 따라 발생하는 번들사이즈에 영향이 없다. 그 이유는, 서버 컴포넌트의 코드는 클라이언트에 fetching되지 않으며 번들사이즈를 줄여주고 런타임 환경까지 진입하는 시간을 줄여주기 때문이다. (자세한 내용은 해당 컨텐츠 이후 자세히 정리해보려 한다.)

위와 같은 이유로 인해, 서버 컴포넌트를 사용함으로써 클라이언트에서 fetching하게 되는 파일의 사이즈가 줄어들어 초기 페이지 렌더 속도가 이전보다 훨씬 빨라지게 된다. 또한 런타임 환경이 로드되었을때 캐싱이 가능하며 번들 사이즈의 예측이 가능해진다. (서버 컴포넌트를 사용함으로써 CSR의 스크립트 파일 용량만 체크하면 되기 때문이다.) 추가로 런타임은 비동기적으로 로드되기 때문에 서버의 HTML이 클라이언트에서 점진적으로 향상될 수 있다.



Data fetching

nextjs에서는 데이터를 가져오고 관리하는 새로운 방법을 도입하였다. 새로운 fetching 방법은 app directory 내부에서 관리되며 서버 컴포넌트 내부에서 데이터를 가져오고 프로미스를 관리하기 위한 fetch 메서드가 가 있다.

// app/page.js
async function getData() {
  const res = await fetch('https://api.example.com/...');
  // The return value is *not* serialized
  // You can return Date, Map, Set, etc.
  return res.json();
}

// This is an async Server Component
export default async function Page() {
  const data = await getData();

  return <main>{/* ... */}</main>;
}
  • fetch 메서드는 reactnextjs에 의해 extends 되었으며, automatic request deduping, caching, revalidating 의 특징이 있다.
// This request should be cached until manually invalidated.
// Similar to `getStaticProps`.
// `force-cache` is the default and can be omitted.
fetch(URL, { cache: 'force-cache' });

// This request should be refetched on every request.
// Similar to `getServerSideProps`.
fetch(URL, { cache: 'no-store' });

// This request should be cached with a lifetime of 10 seconds.
// Similar to `getStaticProps` with the `revalidate` option.
fetch(URL, { next: { revalidate: 10 } });
  • 위와 같이 fetchcache option을 통해 nextjs에서 제공하는 getStaticProps, getServerSideProps, Incriminal Static Regeneration을 대체할 수 있다.


Turbopack alpha

  • 터보팩에 대한 내용은 따로 정리를 할 예정이다.


@next/font

v13 에서는 새로운 폰트 시스템을 도입하였다.

npm install @next/font

위와 같은 커맨드를 통해 모듈 설치 후 사용이 가능하며, 아래와 같은 특징을 가졌다.

  • 커스텀 폰트를 포함한 자동 최적화
  • privacy 및 성능 향상을 위한 외부 네트워크 요청 제거
  • 모든 글꼴 파일에 대한 빌트인 자동 자체 호스팅
  • css의 size-adjust 속성 사용을 통한 제로 layout shift
import NavLink from './NavLink';
import './globals.css';
import { Inter } from '@next/font/google';

const inter = Inter();

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html
      lang="en"
      className={`bg-gray-900 text-gray-100 antialiased ${inter.className}`}
    >
    </html>
  );
}


next/link

Link 컴포넌트의 변경점은 다음과 같다.

  • 더이상 자식 태그로 a를 필요로 하지 않는다.
  • v12.2 전에서는 실험적으로 도입이 되었지만, v13에서는 default로 탑재되었다.
import Link from 'next/link'

<Link href="/movies" className="font-bold">
  Movies
</Link>


next/image

Image 컴포넌트의 변경점은 다음과 같다.

  • 더욱 적은 클라이언트 측 JS 코드 제공
  • configure의 수월함
  • alt default로 요구됨
  • 웹 플랫폼에 맞게 조정
  • hydration을 필요로 하지 않는 Lazy loading으로 인한 속도 증가.


Reference

'NEXT' 카테고리의 다른 글

TIL | Nextjs 환경변수  (0) 2022.01.21
TIL | NEXTjs Build indicator 대신 Loading spinner로 변경하기  (0) 2021.11.30
TIL | Dynamic import  (0) 2021.10.30
TIL | NEXTjs Routing, Dynamic Routes  (0) 2021.10.24
TIL | NEXTjs Pre-rendering  (0) 2021.10.24