akjfal

React18과 Next.js(정리) 본문

공부

React18과 Next.js(정리)

akjfal 2022. 6. 13. 00:09

Overview

React 18이 추가되면서 Suspense를 포함해 자동 업데이트 batching, startTarnsition, React.lazy가 지원되기 시작했습니다. Next 또한 next/streaming을 통해 해당 사항들을 지원하기 시작했다.

※ startTransition : useTransition을 사용해서 다음 화면으로 넘어가기 전 지연을 주는 것

※ batching : 일괄 처리

Using React 18 with Next.js

npm install next@latest react@latest react-dom@lastest

Streaming SSR

Nextjs는 React 18의 Streaming Server-Rendering (SSR)를 바로 사용 가능할 수 있습니다.

Sreaming SSR은 Suspense를 사용한다고 생각하면 됩니다. 주의 사항으로 Vercel과 Node.js 서버에서는 작동하지만 AWS Lambda에서는 작동하지 않습니다. 클라이언트는 서버에게서 stream을 통해서 초기 로딩 이후에 지속적으로 업데이트를 받을 수 있습니다. Suspesne된 컴포넌트가 로드가 시작되면, 서버에서는 렌더를 하고, 보내주게 됩니다. 즉 데이터가 모두 준비되기 전에도 HTML전송이 가능하며, 이를 통해 성능 향상이 이루어질 수 있습니다.

추가적으로 streaming SSR 모드는 선택적 hydration 기능을  추가해줘 성능향상을 기대할 수 있습니다.

non-SSR 페이지들을 위해서, 모든 Suspense boundaries는 여전히 Static Optimization되어져 있습니다.

next/dynamic

React.lazy를 통한 동적 로딩이 React 18에서 더욱 발전했습니다. 기존에는 Suspense나 lazy없이도 next에서 내부적으로 지원을 해주었는데, 지금은 options.suspense와 next/dynamic을 통해서 제공해줍니다.

next/head와 next/script

next/head의 경우 원하는 순서나 타이밍이 Suspense를 추가했을 때 더이상 보장되지 않습니다. 해당 사항들을 next/script의 afterInteractive, lazyOnload, _document로 변경할 것을 추천합니다. 비슷한 이유로 next/script의 beforeInterative를 _document로 옮겨가는 것을 추천합니다.

Data Fetching

현재 Suspense속 data-fetching은 완전히 지원되지 않습니다. 적용했을 때 서버와 클라이언트 사이에서 미스매치가 나타날 수 있습니다.

Styling

Global CSS, CSS 모듈, built-in 'styled-jsx'의 경우 지원됩니다. 곧 해당 가이드를 작성할 것이다. 다른 CSS-in-JS 솔루션들을 적용하기 위한 가이드를 만드는 중입니다.

  • styling code는 server component가 아닌 client component에 위치해야 합니다.

next/streaming

스트리밍 관련 API를 제공하여, Next.js의 기존 기능들을 사용하도록 도와줍니다.

unstable_useWebVitalsReport

성능 측정을 위해서 '_app' 컴포넌트 레벨 함수로 'reportWebVitals'를 제공합니다. 이를 통해 클라이언트 요소에서 Core Web Vitals를 추적 할 수 있습니다.

// pages/_app.server.js
import Layout from '../components/layout.client.js'

export default function App({ children }) {
  return <Layout>{children}</Layout>
}
// components/layout.client.js
import { unstable_useWebVitalsReport } from 'next/streaming'

export default function Layout() {
  unstable_useWebVitalsReport((data) => {
    console.log(data)
  })

  return (
    <div className="container">
      <h1>Hello</h1>
      <div className="main">{children}</div>
    </div>
  )
}

해당 코드처럼 export해서 사용할 수 도 있습니다.

※ Core Web Vitals : 사용자 경험을 위한 구글의 성능 측정, Largest Contentful Paint(LCP), FID(First Input Delay), CLS(Cumulative Layout Shift)가 있다.

unstable_useRefreshRoot

SRC(React Server Component)는 서버에서 렌더링하는데 부분적으로 새로고침이 필요한 경우가 있습니다. 

예를들어, 검색의 경우 타이핑을 하는 동안 검색 결과를 보여줘야합니다. 이를 위해서는 주기적으로 화면을 바꿔줘야합니다.

'unstable_useRefreshRoot'는 반짝임 없이 부드럽게 리엑트 트리를 리렌더링 해주기위해 'refresh'를 리턴해줍니다. 이러한 작업은 클라이언트 쪽에서 허용되며, 서버 구성요소에만 영향을 미칩니다.

// pages/index.server.js
import Search from '../components/search.client.js'
import SearchResults from '../components/search-results.server.js'

function Home() {
  return (
    <div>
      <Search />
      <SearchResults />
    </div>
  )
}
// components/search.client.js
import { unstable_useRefreshRoot as useRefreshRoot } from 'next/streaming'

export default function Search() {
  const refresh = useRefreshRoot()

  return (
    <SearchUI
      onChange={() => {
        refresh()
        // Or refresh with updated props:
        // refresh(nextProps)
      }}
    />
  )
}

React Server Component

서버 컴포넌트는 리엑트 컴포넌트를 서버에서 렌더링 할 수 있도록 합니다. 서버에서 pre-generating HTML을 하는 것과는 근본적으로 다릅니다. 서버 컴포넌트는 클라이언트 js를 필요로 하는데, 렌더링을 더욱 빨리하게 하기 위해서 입니다.

Enable React server Components

1. 최신버전의 리엑트 설치

더보기

npm install next@canary react@lastest react-dom@latest

2. next.config.js 설정

module.export = {
	experimental: {
    	runtime: 'nodejs',
        serverComponents: true
    },
}

runtime : Streaming SSR 을 사용가능하게 합니다. 해당 옵션을 'edge'로 설정 시 완전히 Edge runtime으로 돌아갑니다.

Server Compnents Conventions

서버에서 컴포넌트를 사용하기 위해서는 맨 마지막에 '.server.js'를 붙여줍니다. ex) ./pages/home.server.js

클라이언트 컴포넌트는 '.client.js'를 붙여줍니다. ex) ./components/avatar.client.js

서버 컴포넌트는 서버 컴포넌트와 클라이언트 컴포넌트 둘 다를 import할 수 있는데, 클라이언트 컴포넌트는 서버 컴포넌트를 import하지 못 합니다.

'server'나 'client'가 없는 경우에는 공유 컴포넌트로 취급되어서 두 곳 모두에서 import가 가능합니다.

// pages/home.server.js

import { Suspense } from 'react'

import Profile from '../components/profile.server'
import Content from '../components/content.client'

export default function Home() {
  return (
    <div>
      <h1>Welcome to React Server Components</h1>
      <Suspense fallback={'Loading...'}>
        <Profile />
      </Suspense>
      <Content />
    </div>
  )
}

해당 코드에서 '<Home>'과 '<Profile>' 컴포넌트의 경우 항상 서버 사이드에서 렌더링되고 클라이언트로 이동됩니다. 하지만 클라이언트 사이드 js는 여기에 포함되지 않습니다. 이와 달리 '<Content>'의 경우 클라이언트 사이드로 hydrated 됩니다. 

  • 아직 default로 된 export와 import만 가능합니다. 이름을 통한 export는 구현중입니다.

Supported Next.js APIs

'next/link'and 'next/image'

여전히 해당 api들을 사용할 수 있으며, 클라이언트 컴포넌트로 취급됩니다.

'next/document'

커스텀 '_document'를 가지고 있다면 함수형을 아래 서버 컴포넌트를 사용하는 것으로 바꿔야합니다. 

// pages/_document.js
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  )
}

'next/app'

'_app.js'를 사용중이라면, Custom App과 사용법이 같습니다. 만약 '_app.server.js'를 사용한다면, 아래 children코드를 서버나 클라이언트 코드로 감싸주면 됩니다.

// pages/_app.server.js
export default function App({ children }) {
  return children
}

Routing

path와 쿼리가 포함된 기본 route와 동적 route둘다 지원됩니다. 만약 서버 컴포넌트에 접근하는 router라면, 'router'인스턴스를 사용가능합니다.

// pages/index.server.js

export default function Index({ router }) {
  // You can access routing information by `router.pathname`, etc.
  return 'hello'
}

Unsupported Next.js APIs

아직 alpha단계이기 때문에 모든 기능을 지원하지는 않습니다.

React internals

많은 hook(ex. useContext, useState, useReducer, useEffect)들은 지원되지 않습니다. 서버 컴포넌트들은 stateful하지 않기 때문입니다.

Data Fetching & Styling

styling과 data fetching 등 'Suspense'속 서버 사이드는 지원되지 않습니다. 이는 추후 지원 될 예정입니다.

페이지 레벨에서 export되는 메소드(ex. getInitialProps, getStaticProps, getStaticPaths)들은 지원되지 않습니다.

'next/head' and I18n

이것들을 지원하기 위해 작업중입니다.


Switchable Runtime(Alpha)

Node.js와 Edge Runtime간 페이지를 변경해가면서 해볼수있는 기회입니다.

Nextjs는 Nodejs와 Edge Runtime(클라이언트 측에서 나오는 데이터 작용)를 바꿀 수 있도록 지원합니다. 

Global Rumtime Option

// next.config.js
module.exports = {
  experimental: {
    runtime: 'nodejs',
  },
}

해당 옵션은 어떠한 runtime이 기본 렌더링 런타임으로 사용되는지 결정합니다.

Page Runtime Option

각 페이지 마다 runtime을 'nodejs'나 'edge'로 설정 할 수 있습니다.

export const config = {
  runtime: 'nodejs',
}

서버 구성 요소를 사용하면 개발자는 클라이언트 측 앱의 풍부한 상호 작용성과 기존 서버 렌더링의 향상된 성능을 결합하여 서버와 클라이언트에 걸쳐 앱을 구축할 수 있습니다. Edge Runtime중 일부를 서버에서 처리하도록 할 수 있습니다.

 

'공부' 카테고리의 다른 글

Nextjs dynamic logic(view nextjs source code)  (0) 2022.06.16
24일차  (0) 2022.06.02
22일차  (0) 2022.05.30
21일차  (0) 2022.05.23
20일차  (0) 2022.05.15
Comments