이렇게 레거시 코드가 되버려.. 2편 그리고 끗 (feat. Next.13)

박정훈·2022년 11월 5일
1

Next.js

목록 보기
2/5

1편에 이어서 여기부터 읽는다. Streaming

스트리밍이 뭐양.. 점진적으로 데이터가 흐른다는건가...

Streaming

Next.js의 서버 컴포넌트와 중첩 레이아웃을 사용하면 데이터가 특별히 필요하지 않은 페이지의 일부를 즉시 렌더할 수 있고, 데이터를 fetching하는 페이지의 일부에 loading state를 보여줄 수 있다. 이 접근방식으로 사용자는 전체적인 page와 상호작용 하기전에 전체 페이지가 로드될 때까지 기다릴 필요가 없다.

Vercel에 배포되면 app 디렉토리를 사용하는 Next.js 13 앱은 성능향상을 위해서 기본적으로 Node.js와 Edge runtimes 모두에서 응답을 stream 한다.

설명이 부족해! Beta 버전을 스윽 살펴볼까나.

Learn more about streaming

Data Fetching Fundamentals

Next.js는 앱에서 data를 fetch하는 새로운 방식을 제시한다. API가 React 및 웹 플랫폼에 맞게 간소화 되었다. 즉, app directory에서 getServerSideProps, getStaticProps, 그리고 getInitialProps를 더이상 지원하지 않는다는 것을 의미한다.

대신! 컴포넌트 레벨에서 data를 fetch하고, cache하고, 재검증할 수 있는 방법이 있다.

여기서는 앱의 data 생명주기를 관리하는 fundamental conceptsbest practice에 대해서 설명한다. (두근두근)

Fetching Data with Server Components

app directory안에서, 직접적으로 데이터가 필요한 Server Components 내부에서 data를 fetching 하는것이 좋다.

Server Components는 항상 서버에서 data를 fetch한다.

Server Components내부에서 data를 fetching하는것은 다음과 같은 매우 많은 이점을 가진다.

  • 백엔드 데이터 리소스에 직접 접근할 수 있다. 클라이언트에서 절대로 실행되지 않기 때문이다.
  • 서버에 있는 acess tokens 및 API keys와 같은 앱의 민감한 정보를 쉽게 보호할 수 있다.
  • Fetch data와 component render를 같은 환경에서 한다. 클라이언트와 서버간의 통신뿐만 아니라 클라이언트 측의 메인 스레드 작업 모두 줄어든다.
  • multiple data fetches를 클라이언트에서 여러번의 개별 요청 대신! 한번의 왕복으로 수행한다. 지역에 따라서는 data fetching이 데이터 소스에 더 가까이서 수행될 수 있고, 이는 대기 시간을 줄이고 성능을 향상시킬 수 있다.
  • 클라이언트 서버의 waterfalls를 줄인다(?)
  • 서버 컴포넌트는 JS bundle을 보내지 않으므로 클라이언트에 더 적은 JS를 보냅니다.

이러한 새로운 모델에서는 여러 컴포넌트에서 같은 data를 요청하는 경우에도, 우리(Next.js)는 data를 props를 통해 다른 Server Components로 보내는 대신, 필요로 하는 Server Components 내부에서 직접 data를 fetching하는것을 추천한다.
background에서 React와 Next.js는 동일한 데이터를 두번 이상 가져오는것을 피하기 위해서 cache와 중복제거를 한다.

현재 클라이언트 컴포넌트에서는 fetch가 지원되지 않는다. 예를 들어 SWR과 같은 서드 라이브러리를 사용해서 fetch가 가능하지만, 이는 성능상의 이슈를 일으킬 수 있다. 가능하다면 use를 사용하거나 fetch를 사용해서 Server Components 안에서 data fetching logic을 유지하고, data를 클라이언트 자식 컴포넌트로 내려주라고 하네요.

부모 레이아웃과 자식 간에 데이터를 전달할 수 없다. 그렇지만, 동일한 data를 route에서 한 번 이상 가져올 수 있고, React는 자동으로 성능에 영향을 주지 않고 요청을 중복제거한다.

Component-level Data Fetching

app 디렉토리에서는 layout, pages, 그리고 components안에서 data를 fetch할 수 있다. 그러나 컴포넌트 레벨에서 data를 fetching 하는것은 어떻게 React 작업과 동시성을 가질지(?), 특히 Streaming과 Suspense와 호환되어야 한다.

The fetch() API and Async Components

새로운 data fetching 방식은 native Web API위에서 구축되며 Server Components내부에서 async/await을 사용한다. Promises RFC는 슬쩍 넘어간다.

fetch()는 원격 리소스를 fetch하는데 사용되며 promise를 반환한다. React는 fetch를 확장해서 자동 요청 중복 제거를 제공하고, Next.js는 fetch의 옵션 객체를 확장해서 각 요청이 캐싱 및 재검증 규칙을 따를 수 있도록 했다.

Automatic fetch() Request Deduping

React는 동일한 입력의 fetch 요청을 temporary cache에서 자동으로 cache한다. 이는 redering pass동안에 data가 두 번 이상 fetch되는 것을 방지하기 위한 최적화이며, 특히 여러 컴포넌트에서 같은 데이터를 가져와야 할 때 유용하다.

예를 들어, 중첩된 레이아웃에 걸쳐 있는 트리의 여러 컴포넌트 안에서 현재 사용자를 fetch할 수 있다. 이 최적화는 안전할 뿐만 아니라 사용되는 컴포넌트에서 데이터를 fetch하도록 권장한다.

  • 서버에서 캐시는 rendering process가 완료될 때까지 서버 요청의 생명주기를 유지한다.
  • 클라이언트에서 캐시는 전체 page를 다시 로드하기 전에 session 기간동안 유지한다.(?)

fetch를 사용할 수 없는 경우에 React는 요청 동안에 데이터를 캐시할 수 있는 cache function을 제공한다.

Static and Dynamic Data Fetches

Next.js에서는 Static과 Dynamic, 두 가지 타입의 데이터가 있다.

  • Static Data는 자주 바뀌지 않느다. 거의 업데이트 되지 않는 blog post와 같은 것들!
  • Dynamic Data는 자주 바뀌거나 유저에게 특정될 수 있는 데이터다. 장바주니 같은 것들!

기본적으로 Next.js는 자동으로 static fetch를 수행한다.

예?

즉, 데이터는 build time에 불러와지고, cache 되며, 각각의 요청에 재사용된다. 개발자는 정적 데이터의 캐시 및 재검증 방식을 컨트롤 할 수 있다.
정적 데이터를 사용하는 것에는 두가지 이점이 있다.
1. 요청수를 최소화하여 데이터베이스의 부하를 줄일 수 있다.
2. 데이터는 로딩 성능 향상을 위해 자동으로 캐시된다.

그러나 최신 데이터를 가져고오 싶은 경우도 있다. Next.js는 요청을 동적으로 할 수 있게 지원한다. 즉, 데이터는 요청 때 불러와지고 캐시되지 않는다.

Caching Data

캐싱은 CDN과 같은 곳에 데이터를 저장화는 과정이기에 각 요청에 대해 원본 데이터로부터 다시 가져올 필요가 없다.

Next.js 캐시는 전역으로 퍼트릴 수(distribute) 있는 영구적인 HTTP 캐시이다. 즉, 캐시를 자동으로 확장할 수 있고, 플랫폼에 따라 여러 지역에서 공유 가능하다.

server rendering동안에 Next.js가 fetch를 발견하면 캐시를 확인하여 데이터가 사용 가능한지 확인한다. 사용 가능하다면, 캐시된 데이터를 return 하고, 그렇지 않으면 fetch 하고 데이터를 저장한다.

Revalidating Data

재검증은 캐시를 정리하고, 최신 데이터를 다시 가져오는 프로세스다. 이 기능은 당신의 데이터가 바뀌었을 떄 당신의 앱이 최신 버전을 보여줄 수 있도록 보장하고자 할 때 유용하다.

Next.js는 두가지의 재검증 타입을 제공한다.

  • Background: 특정 시간 간격에 따라 데이터를 재검증한다.
  • On-demand: 업데이트가 있을 때마다 데이터를 재검증한다.

on-demand 재검증은 미래에 더 추가될 것이다.

Streaming and Suspense

Streaming과 Suspense는 클라이언트에 UI의 단위(units of the UI)를 점진적으로 렌더링하고, 점진적으로 스트림 렌더링하는 새로운 React 기능이다.

Streaming and Suspense are new React features that allow you to progressively render and incrementally stream rendered units of the UI to the client.

Server Components와 중첩된 레이아웃에서 특별히 데이터가 필요하지 않은 페이지는 즉시 렌더되고, 데이터를 불러오는 일부 페이지에 대해 loading state를 보여줄 수 있다. 즉, 사용자는 페이지와 상호작용을 하기 전에 전체 페이지가 로드되기를 기다릴 필요가 없다.

Parallel and Sequential Data Fetching

Next.js는 두가지 데이터 패칭 패턴을 지원한다. (병렬과 순차)

Parallel data fetching

요청들이 in a route에서 활발하게 시작되며 동시에 데이터를 로드한다. 이는 클라이언트 서버의 waterfalls를 감소하며 데이터를 로드하는 총 시간이 줄어든다.

Sequential Data Fetching

in a route의 요청들이 서로에게 의존하며 waterfall 패턴으로 데이터를 로드한다. 하나의 fetch가 다른 결과물에 의존하거나, 다음 fetch이전에 자원을 절약하기 위해 조건을 충족하기를 원하는 경우가 있을 수 있다.(?) 그러나 순차적으로 데이터를 가져오는 것은 의도치 않게 로드 시간이 길어질 수 있다.

Streaming 파트 끗! 다시 Next.js 13으로!

Data Fetching

Web API의 native fetch는 React와 Next.js에서 확장되었다. 컴포넌트 레벨에서 자동으로 fetch 요청을 중복 제거 하며, 캐싱하고, 재검증한다. 즉, SSG, SSR, ISR이 이제는 하나의 API로 쌉가능이다.

// 이 요청은 수동으로 무효화 될 때까지 캐시되어야 한다.
// getStaticProps와 비슷하다.
// 'force-cahe'는 기본값이며 생략 가능하다.
fetch(URL, { cache: 'force-cache' });

// 이 요청은 매 요청마다 refetch되어야 한다.
]// 'getServerSideProps'와 비슷하다.
fetch(URL, { cache: 'no-store' });

// 이 요청은 10초동안 캐시되어야 한다.
// 'revalide' 옵션이 있는 'getStaticProps'와 비슷하다.
fetch(URL, { next: { revalidate: 10 } });

app 디렉토리 안에서는 서버로부터의 streaming responses지원을 포함해서 layouts,pages그리고 components안에서 데이터를 불러올 수 있다.

Introducing Turbopack (Alpha)

Next.js는 웹팩의 새로운 Rust기반 후속작인 Turbopack을 포함한다.

웹팩은 30억번 이상 다운로드 되었다... 웹 구축에 필수적인 요소였지만, JS기반의 tooling으로 가능한 최대 성능의 한계에 봉착했다.

Next.js 12에서는 native Rust-powered tooling으로 전환하기 시작했다.

We started by migrating away from Babel, which resulted in 17x faster transpilation. Then, we replaced Terser, which resulted in 6x faster minification.

Turbopack alpha를 Next.js 13와 함께 사용하면]

  • 웹팩보다 700배 빠른 업데이트
  • Vite보다 10배 빠른 업데이트 🧐
  • 웹팩보다 4배 빠른 cold start

다음과 같은 글이 이따...
진짜 Vite보다 10배 빠르다고?

Next.js의 Turbopack은 오직 next dev만 지원한다. next build에 대한 지원을 추가하기 위한 작업을 진행중이다.

Try out the Turbopack alpha today in Next.js 13 with next dev --turbo.

Next/image

Nextjs는 성능을 향상시키기 위해 레이아웃 변경 없이 이미지를 쉽게 표시하고 온디맨드 방식으로 파일을 최적화는 강력한 새로운 이미지 컴포넌트다.

더욱 강력해진 이미지 컴포넌트를 소개한돠!

  • 클라이언트 측 JS가 적게 제공된다. (Ships less client-side JavaScript)
  • style 및 configure가 쉽다.
  • 더욱 좋은 접근성을 위해 alt 태그가 default (More accessible requiring alt tags by default)
  • 웹 플랫폼에 맞게 조정 (Aligns with the Web platform)
  • native lazy loading은 hydration이 필요 없기 때문에 더 빠르다.
import Image from 'next/image';
import avatar from './lee.png';

function Home() {
  // "alt" is now required for improved accessibility
  // optional: image files can be colocated inside the app/ directory
  return <Image alt="leeerob" src={avatar} placeholder="blur" />;
}

Upgrading next/image to Next.js 13

힝... 오래된 이미지 컴포넌트 next/legacy/image로 변경되었다.

We've provided a codemod that will automatically update your existing usage of next/image to next/legacy/image. For example, this command would run the codemod on your ./pages directory when run from the root:

npx @next/codemod next-image-to-legacy-image ./pages

next/font

Next.js 13은 새로운 폰트 시스템을 도입해똬!

  • custom fonts를 포함해서 자동으로 폰트 최적화
  • privacy와 퍼포먼스를 향상 시키기 위해 외부 네트워크 요청을 제거
  • 모든 폰트 파일에 대한 자동 내장 호스팅
  • CSS의 size-adjust 속성을 사용해서 자동으로 Zero layout shift.(?)

새로운 폰트 시스템을 사용하면 성능과 개인정보 보호를 염두에 두고 모든 Google Fonts를 사용할 수 있다.
CSS 및 폰트 파일은 build time에 다운로드 되고, 나머지 정적 assets들과 함께 self-hosted 된다. 브라우저에서 Google로 요청을 보내지 않는다.

import { Inter } from '@next/font/google';

const inter = Inter();

<html className={inter.className}>

self-hosting, 캐시, 폰트 파일 프리로딩을 포함한 custom fonts 또한 지원된다.

import localFont from '@next/font/local';

const myFont = localFont({ src: './my-font.woff2' });

<html className={myFont.className}>

next/link에서 더이상 a 태그를 자식으로 추가할 필요가 없당. Next.12에서 실험 옵션이었고, 현재는 default다. Next.js 13에서 Link 태그는 항상 a를 렌더링한다.

To upgrade your links to Next.js 13, we've provided a codemod that will automatically update your codebase. For example, this command would run the codemod on your ./pages directory when run from the root:

npx @next/codemod new-link ./pages

내용 많당. 그리고 신기하다. 이 사람들은 무슨 생각을 가지고 살까. 오로지 Next.js에 진심이지 않을까

정리는 여기까지 하려고 한다.
이후에도 OG Image Generation 와 Middleware API Updates 내용이 있다. 물론 읽어봤지만 솔직히 잘 모르겠다. 미들웨어 같은경우는 12버전의 내용을 읽어봐야겠다. 히히

공식문서를 한땀한땀 읽어본건 정말이지... 거의 처음이라고 해도 과언이 아니다. 생각보다 힘들었고 생각보다 즐거웠다. (뭔소리지?) 공식문서에서도 반복적으로 강조하는 부분이 있다는 것을 알았고, 여러 표현들을 써가며 설명하려고 애쓴 흔적이 보였다.

사실 Next.js 13버전이 릴리즈 되기전에 React공식 문서를 한땀 한땀 읽어나가고 있었다. 그것도 읽으면서 한번 쭉 정리를 해 보고 있었는데 마침 얘가 나와서... 궁금증에 읽어본다는게 우선순위가 바뀌어 버렸...네요... 이제 얘는 다 정리했으니 다시 훑어보고(벌써 1편의 내용이 가물가물하다! 세상에!) React로 넘어가려고 한다.

사이드프로젝트의 13버전으로의 마이그레이션도 얘기가 나오고 있다.

할게 정말 많고 서류는 미친듯이 떨어지고 있다. 사실 이걸 정리하는것보다 이력서 손보고 프로젝트 리팩토링이 더 급한것도 사실이다. 지원도 계속 해야하고! 그래도 중간 중간 환기차 읽어보면서 정리한거니까... 이러한 습관이 나에게 큰 자산으로 남길 바란다.

profile
그냥 개인적으로 공부한 글들에 불과

1개의 댓글

comment-user-thumbnail
2022년 11월 6일

읽기 싫어서 같이 읽기 스터디 하실래요? 하려고 했는데 까비!

답글 달기