Next 맛보기!

신은수·2023년 11월 20일
0

NextJS

목록 보기
1/1

1. PreRender와 Hydrate

  • Next.js에선 기본적으로 모든 페이지를 PreRender한다. 즉 HTML이 클라이언트 사이드에서 자바스크립트를 통해 생성이 되는 게 아니라 Next.js가 사전에 각 페이지를 만들어 놓는다. 이때 각 HTML은 해당 페이지에 최소한으로 필요한 자바스크립트 코드와 결합되어있다.

  • 페이지가 브라우저에 의해 로드될 때는 hydration이라는 프로세스를 거치게 된다. hydration은 자바스크립트 코드가 실행되어 해당 페이지를 완전히 인터렉티브하게 만드는 것을 의미한다.

  • 프리 렌더링을 할 경우, 프리 렌더링을 하지 않을 때보다 더 나은 성능과 SEO를 갖출 수 있다.

  • Next.js는 프리 렌더링 및 서버사이드 렌더링을 포함한 페이지 렌더링을 위한 런타임으로 Node.js를 사용한다.


2. SSR과 SSG차이

  • Next.js의 pre-rendering 형태는 Static Generation과 Server Side Rendering으로 나뉘며 각 페이지별로 다르게 적용할 수 있다. 이 pre-rendering 방식의 차이는 HTML을 생성할 때에 있다.

  • 서버에서 요청할 때 즉시만드느냐 혹은 미리 만들어 놓느냐에 따라 차이가 있다.

  • SSR은 요청시 서버에서 즉시 HTML을 만들어서 응답하기 때문에 데이터가 달라져서 미리 만들어 두기 어려운 페이지에 적합하다.

  • 반면 SSG는 미리 다 만들어두고 요청시에 해당 페이지를 응답하기 때문에 바뀔일이 거의없어서 캐싱해두면 좋은 페이지에 사용된다.


3. Next 14에서 업데이트 된 내용

1) Routing

  • 기존에 pages/ 디렉토리에서 라우팅 되던 방식과 다르게, app/ 디렉토리로 라우팅 하는 방식이 추가됨
  • app/ 디렉토리를 생성하여 라우팅을 설정할 수 있으며, 라우팅 환경 개선 뿐만 아니라, 레이아웃, 서버 컴포넌트, 스트리밍, 데이터 패칭까지도 지원하는 형태로 향상
  • 기존 pages 라우터 방식

    // pages/index.js
    export default function Page() {
      return <h1>Hello, Next.js!</h1>;
    }
  • 새로운 앱 라우터 방식

    // app/layout.js
    export default function RootLayout({ children }) {
      return (
        <html lang="en">
          <body>{children}</body>
        </html>
      );
    }
    
    // app/page.js
    export default function Page() {
      return <h1>Hello, Next.js!</h1>;
    }

Route Segments (경로 세그먼트)

경로의 각 폴더는 경로 세그먼트를 나타낸다. 각 경로 세그먼트는 URL 경로의 해당 세그먼트에 매핑된다.

Component Hierarchy (구성 요소 계층)

  • 경로 세그먼트의 특수 파일에 정의된 React 구성 요소는 특정 계층 구조로 렌더링된다.

    • layout.js
    • template.js
    • error.js (React error boundary)
    • loading.js (React suspense boundary)
    • not-found.js (React error boundary)
    • page.js or nested layout.js

Dynamic Routing (동적 경로)

  • 정확한 세그먼트 이름을 미리 모르고 동적 데이터에서 경로를 생성하려는 경우 동적 세그먼트를 사용할 수 있다.
    export default function Page({ params }: { params: { slug: string } }) {
      return <div>My Post: {params.slug}</div>
    }
    app/blog/[slug]/page.js => /blog/a => { slug: 'a' }

Parallel Routing (병렬 경로)

병렬 라우팅을 사용하면 동일한 레이아웃에서 하나 이상의 페이지를 동시에 또는 조건부로 렌더링할 수 있다.

2) React Server Component

  • app directory 내부에서는 모든 컴포넌트가 기본적으로 서버 컴포넌트로 동작함
    • 서버 컴포넌트 vs 클라이언트 컴포넌트: 컴포넌트가 렌더링 되는 장소가 서버인지 클라이언트인지의 차이. 서버 컴포넌트는 서버에서 한 번 해석 된 후 클라이언트로 전달됨
    • 클라이언트 컴포넌트는 서버에서도 렌더링되고 클라이언트에서도 렌더링(hydration)되고, 서버 컴포넌트는 서버에서 렌더링 되고 클라이언트에서 hydrate되지 않는다.
  • 서버 컴포넌트는 서버에서 먼저 render되고 hydrate되지는 않는다.
    • 서버 컴포넌트는 복잡한 인터페이스를 구축하는 동시에 클라이언트로 전송되는 JavaScript의 양을 줄여, 초기 페이지 로드 속도를 높일 수 있음. 또한, 경로(route)가 로드될 때, Next.js 및 React 런타임이 로드되어 캐시가 가능하고 크기를 예측할 수 있음
  • 클라이언트 컴포넌트: 만약 app directory 내부에서 클라이언트 컴포넌트를 사용하고 싶다면 파일 최상단에 use client라는 directive를 명시해야 함
    • useState, useEffect 훅을 사용하는 경우
    • 특정 브라우저 API에 의존성이 있는 경우
    • 특정 Event Listeners를 추가하는 경우

3) Streaming

  • React 및 Next.js에서 스트리밍이 작동하는 방식을 배우려면 SSR(서버 측 렌더링)과 그 제한 사항을 이해하는 것이 좋다.

    • 먼저, 특정 페이지의 모든 데이터를 서버에서 가져온다.
    • 그런 다음 서버는 페이지의 HTML을 렌더링한다.
    • 페이지의 HTML, CSS, JavaScript가 클라이언트로 전송된다.
    • 생성된 HTML 및 CSS를 사용하여 비대화형 사용자 인터페이스가 표시된다.
    • 마지막으로 React는 사용자 인터페이스를 대화형으로 만들기 위해 수분을 공급한다.
  • 이 단계는 순차적이고 차단적이다. 즉, 모든 데이터를 가져온 후에만 서버가 페이지에 대한 HTML을 렌더링할 수 있다. 그리고 클라이언트에서 React는 코드가 로드된 후에만 UI를 수화할 수 있다.

  • 스트리밍을 사용하면 페이지의 HTML을 더 작은 청크로 나누고 점진적으로 해당 청크를 서버에서 클라이언트로 보낼 수 있다.

  • 이를 통해 UI가 렌더링되기 전에 모든 데이터가 로드될 때까지 기다리지 않고 페이지의 일부를 더 빨리 표시할 수 있습니다. 우선순위가 더 높거나 데이터에 의존하지 않는 구성 요소가 먼저 전송될 수 있으며 React는 더 일찍 수화를 시작할 수 있다.

  • 또한, loading.js 파일을 만들어서 트리밍 형태의 로딩 UI를 생성할 수 있음. loading.js 파일을 생성하면 React Suspense를 자동으로 래핑하여 로딩 화면을 보여주고, 라우트 세그먼트의 내용을 로드하는 동안 서버에서 즉시 로딩 상태를 표시하고, 렌더링이 완료되면 자동으로 새로운 콘텐츠로 교체됨

4. Data Fetching

  • fetch() Web API를 사용할 수 있게 되면서, 이제는 컴포넌트 레벨에서도 SSR의 적용이 가능함.
  • React는 fetch() API의 중복제거를 제공하며, Next.js는 캐싱과 재요청 처리까지 지원하려고 함.
  • 이를 통해, 기존의 SSG, SSR, ISR(Incremental Static Regeneration) 등의 기법을 아래와 같은 fetch() 옵션으로 대체 가능
// 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 } });

출처
Next.js 13 업데이트 된 내용 정리 & App 라우터 자세히 알아보기

Next 공식문서

profile
🙌꿈꾸는 프론트엔드 개발자 신은수입니당🙌

0개의 댓글