Next.js · Routing

App Router Render Tree

URL 세그먼트, 중첩 구조, 렌더 순서 세 가지를 하나로 연결합니다. 자식이 부모 안에 실제로 들어간 모양의 중첩 상자로 표현하며, 재생하면 RSC 셸 → Suspense 스트리밍 → 클라이언트 수화 순서로 나타납니다.

0% · RSC 셸
RSC 서버 컴포넌트Suspense 경계'use client'
localhost:3000세그먼트에 마우스를 올리면 대응하는 트리 노드가 강조됩니다 (`42`는 `[id]` 동적 세그먼트)
RSC 셸Suspense 스트리밍클라이언트 수화
RSC 셸—서버가 RSC 셸을 바깥 레이아웃부터 안쪽 page까지 차례로 만든다.
  • Root Layoutapp/layout.tsx

    <html>/<body>를 소유하는 서버 컴포넌트. 라우트가 바뀌어도 다시 렌더되지 않고 그대로 유지된다.

  • Products Layoutapp/products/layout.tsx

    products 세그먼트가 소유하는 중첩 레이아웃. 상품 목록과 상세가 공통으로 쓰는 껍데기다.

  • Product Pageapp/products/[id]/page.tsx

    [id] 동적 세그먼트를 params로 받아 하위를 합성한다. 여기까지가 즉시 flush 되는 셸이다.

  • ProductDetails<Suspense fallback={<Skeleton/>}>

    await getProduct(id)가 끝날 때까지 스켈레톤이 자리를 지킨다. 이 경계 밖은 이미 화면에 떠 있다.

  • ImageGallery'use client' Carousel.tsx

    썸네일 클릭·스와이프를 처리하는 클라이언트 컴포넌트. HTML은 부모와 함께 도착하지만, 수화되기 전까지는 눌러도 반응하지 않는다.

  • Reviews<Suspense fallback={<Skeleton/>}>

    await getReviews()는 더 느리지만 ProductDetails를 기다리게 하지 않는다. 경계마다 독립적으로 도착한다.

  • AddToCartButton'use client' AddToCart.tsx

    장바구니 담기 onClick을 소유한다. 선택적 수화 덕분에 이 버튼을 먼저 누르면 우선순위가 이쪽으로 옮겨진다.