[BFE.dev] Suspense 2

치만·2026년 1월 15일

BFE.dev react

목록 보기
8/28
post-thumbnail

Suspense 2

// This is a React Quiz from BFE.dev 

import * as React from 'react'
import { Suspense } from 'react'
import { createRoot } from 'react-dom/client'

const resource = (() => {
  let data = null
  let status = 'pending'
  let fetcher = null
  return {
    get() {
      if (status === 'ready') {
        return data
      }
      if (status === 'pending') {
        fetcher = new Promise((resolve, reject) => {
          setTimeout(() => {
            data = 1
            status = 'ready'
            resolve()
          }, 100)
        })
        status = 'fetching'
      }

      throw fetcher
    }
  }
})()

function A() {
  console.log('A1')
  const data = resource.get()
  console.log('A2')
  return <p>{data}</p>
}

function B() {
  console.log('B')
  return null
}

function Fallback() {
  console.log('fallback')
  return null
}

function App() {
  console.log('App')
  return <div>
    <Suspense fallback={<Fallback/>}>
      <A/>
      <B/>
    </Suspense>
  </div>
}

const root = createRoot(document.getElementById('root'));
root.render(<App/>)

출력 결과

"App"
"A1"
"B"
"fallback"
"A1"
"A2"
"B"

풀이 과정

1. 초기 렌더링

  • App 출력: root.render(<App/>)에 의해 App 컴포넌트가 호출됩니다.

  • A1 출력: App 내부의 A가 실행됩니다.

    • 중단(Suspend) : 컴포넌트 Athrow에 의해 실행이 중단됩니다.
  • B 출력: App 내부의 B가 실행됩니다.


2. Fallback 처리

  • Suspense가 에러(Promise)를 캐치: React는 위에서 던져진 Promise를 감지합니다.

  • fallback 출력: Promise가 처리되는 동안 보여줄 Fallback 컴포넌트를 렌더링합니다.


3. Promise 완료 후 재렌더링

✨ React는 Promise가 해결되었으므로 중단되었던 부분부터 다시 그리려 합니다.
React는 효율성을 위해 App 전체를 다시 그리는 것이 아니라, Suspense 경계 내부인 <A/><B/>만 다시 실행합니다.
그래서 App 로그가 다시 찍히지 않는 것입니다.

  • A1 출력: A 컴포넌트가 처음부터 다시 실행됩니다.

  • A2 출력: 데이터를 반환하고 A2가 출력됩니다.

  • B 출력: 나중에 데이터가 준비되어 다시 그리기로 결정하면, Suspense 내부에 있는 모든 자식 컴포넌트(AB 전체)를 처음부터 다시 렌더링합니다.

profile
🌱개발 기록장

0개의 댓글