Streaming

React와 Next.js에서 사용한 SSR은 사용자에게 비대화형 UI를 가능한 빨리 표시하여 인지되는 로딩 성능을 향상시키는 데 도움이 됨. 그러나 페이지가 사용자에게 표시되기 전에 서버에서 모든 데이터를 가져와야 하므로 여전히 느릴 수 있음

이때, 스트리밍 방식의 렌더링을 사용하면 페이지의 HTML을 더 작은 덩어리로 나누고, 점진적으로 해당 덩어리를 서버에서 클라이언트로 보낼 수 있음. 이를 통해 모든 데이터가 로드될 때까지 기다리지 않고 페이지의 일부를 더 빨리 표시할 수 있음. 그렇기에 더 나은 사용자 경험(UX) 개선을 위해 스트리밍을 사용함

Suspense

비동기 작업을 수행하는 컴포넌트를 래핑하고 해당 작업이 진행되는 동안 대체 UI를 표시한 다음, 작업이 완료되면 컴포넌트를 교체하는 방식으로 동작함

다운로드.png

다운로드 (1).png

다운로드 (2).png

Suspense로 둘러싼 단위로 페이지의 HTML을 덩어리로 나누어 서버에서 클라이언트로 보낼 수 있기 때문에, 어느 범위를 Suspense로 감쌀지 설계가 중요함. 비동기 작업을 Suspense로 래핑하면 해당 작업이 진행되는 동안 fallback Props의 대체 UI를 화면에 보여줌

<section className="h-auto py-4 md:h-[calc(100%-56px)]">
  <Container className="flex h-full items-center justify-center">
    <GridContainer>
      <GridItem className="row-span-2 h-[300px]">
        <Weather />
      </GridItem>
      <GridItem className="row-span-2 h-[300px]">
        <MyCheckList />
      </GridItem>
      <GridItem className="row-span-1 h-[184px]">
        <NewArrivals />
      </GridItem>
      <GridItem className="row-span-1 h-[184px]">
        <NewUpdates />
      </GridItem>
    </GridContainer>
  </Container>
</section>
export default function GridItem({
  children,
  className,
}: PropsWithChildren<GridItemProps>) {
  return (
    <article
      className={`${className} card-shadowed w-full rounded-md px-4 py-3 text-black md:max-w-[280px]`}
    >
      <ErrorBoundary FallbackComponent={ErrorUI}>
        <Suspense fallback={<LoadingUI />}>{children}</Suspense>
      </ErrorBoundary>
    </article>
  )
}

결과

Streaming 적용 전 새로고침

Streaming 적용 전 새로고침

Streaming 적용 후 새로고침

Streaming 적용 후 새로고침

변경 전에는 모든 데이터가 로드될 때까지 전체 로딩 UI를 보여줬지만 변경 후에는 개별적으로 로딩 UI를 보여주며 점진적 로딩을 발생시킴

만약, 사용자 기기의 사양이나 네트워크가 좋지 않을 경우 전체 데이터를 로드하기 까지 오랜 시간이 걸려 좋지 못한 사용자 경험을 제공했다면, 스트리밍 서버 렌더링을 사용함으로써 좋지 않은 환경의 사용자에게 또한 빠른 렌더링을 제공할 수 있게 되었음