Post

[NextJS] 정적 렌더링, 동적 렌더링, 스트리밍

정적 렌더링

  • 빌드 시점(배포) 또는 데이터 재검증 시점에 서버에서 미리 렌더링 해놓는 것을 뜻한다.
  • 미리 만들어져 있는 정적인 페이지를 캐시하여 페이지 로딩 속도를 빠르게 할 수 있다.
  • 데이터가 없거나 정적인 페이지에 유용하다.

동적 렌더링

  • 동적 API를 호출하거나 데이터가 캐시되지 않은 경우 동적으로 렌더링한다.
  • ‘동적’이라는 뜻은 바뀔 수 있다는 의미이며, 요청 시점에서만 알 수 있는 정보로 페이지를 렌더링 할 수 있다.
  • 비용이 많이 드는 데이터는 캐시 처리하거나, 분할하여 스트리밍 할 수도 있다.

동적 API

  • 사전 렌더링 시점에 알 수 없는 정보(ex. 쿠키, 헤더 등)로 API를 요청하는 경우 동적 API라고 한다.

스트리밍

스트리밍은 서버에서 데이터를 청크로 분할하여 클라이언트에게 점진적으로 전송할 수 있는 기술이다.

스트리밍 기법을 통해 사용자는 서버의 느린 데이터 페치가 완료될 때까지 기다리지 않고 페이지의 일부를 보고 상호작용 할 수 있다.

스트리밍을 구현하는 방법에는 라우팅 경로에 loading.tsx 파일을 생성하거나, <Suspense> 컴포넌트를 사용하는 방법이 있다.

스트리밍의 원리

  • 서버에서는 html 파일을 점진적으로 로드하는데, 데이터를 페치하는 동안 노출할 fallback UI와 데이터 페치가 완료된 후 데이터를 노출할 곳을 미리 표시한 placeholder를 먼저 전송한다.
    • (이 때 placeholder는 비어 있다.)
1
2
3
4
5
6
7
8
9
10
11
<Suspense fallback={<div>loading...</div>}>
  <DynamicContent />
</Suspense>

<!-- 위 리액트 코드는 아래 형식의 html 청크로 전송된다. -->
<!--$?-->
<div>
    <template id="B:0"></template>
    <div>loading...</div>
<div>
<!--/$-->
  • <!--$?-->, <!--/$--> 표시는 리액트에서 정의한 리터럴로 Suspense 경계를 식별하는데 사용된다.
  • 이후 데이터 페칭이 완료되면 서버는 후속 데이터 청크를 전송한다.
1
2
3
4
5
6
7
8
9
<div hidden id="S:0">
  <p>Hello, World!</p>
</div>
<script>
  $RC = function (b, c, e) {
    ...
  };
  $RC("B:0", "S:0");
</script>
  • $RC 함수는 fallback UI를 숨기고 새로운 데이터(S:0)를 삽입하는 역할을 한다.

참고사이트

부분 사전 렌더링

  • NextJS 14 버전부터 도입된 정적 렌더링과 동적 렌더링을 결합할 수 있는 렌더링 모델
  • 동적 컨텐츠에 <Suspense> 컴포넌트를 사용하여 구현
  • 정적 컨텐츠는 사전 렌더링하고, 동적 콘텐츠는 스트리밍으로 렌더링
  • 실험적 기능이며 아직 프로덕션은 지원X
    • 개발 모드에서는 데이터를 페칭하는 동안 html 문서에 fallback UI가 내려오지만, 빌드 모드에서는 동적 렌더링까지 완료된 후 html 문서가 전송되는 것 같음

부분 사전 렌더링 과정

  1. 배포 시점에 부분적으로 사전 렌더링 된 정적 컨텐츠가 배포된다.
  2. 사용자가 페이지를 방문하면 1번에서 만든 정적 컨텐츠를 즉시 렌더링하고, 동적 컨텐츠 렌더링을 서버에 요청해놓는다.
  3. 클라이언트는 정적 자산(폰트, 이미지, 스크립트)을 다운로드하며 사전 렌더링된 HTML을 화면에 그리기 시작한다. React는 유저 인터페이스를 hydrate해서(자바스크립트 이벤트와 상태를 연결하는 과정) 상호작용이 가능하게 만든다.
  4. 서버에서 동적 컨텐츠의 청크가 준비되면 클라이언트에 스트리밍한다.
  5. 클라이언트는 fallback UI를 동적 콘텐츠로 대체한다.

참고사이트

This post is licensed under CC BY 4.0 by the author.