use와 Suspense의 관계

292025년 09월 13일3

use 훅은 그 자체로도 혁신적이었지만, 그 진정한 힘은 Suspense와 함께일 때 비로소 완성되었다. 이 둘은 처음부터 하나의 목표를 위해 설계된, 완벽하게 협력하는 파트너였다.

use 훅은 신호를 보내는 역할이고, Suspense는 그 신호를 받아 처리하는 역할입니다.”

앤드류 클라크는 팀원들에게 두 기능의 관계를 명확히 설명했다. 그는 간단한 컴포넌트 트리를 화이트보드에 그렸다.

<App>
  <Suspense fallback={<PageSpinner />}>
    <Layout>
      <Header />
      <Suspense fallback={<PostSkeleton />}>
        <PostDetails />
      </Suspense>
    </Layout>
  </Suspense>
</App>

그리고 PostDetails 컴포넌트의 내부 코드를 옆에 적었다.

// PostDetails.js
function PostDetails() {
  const post = use(fetchPost()); // <--- 여기서 Promise가 처리 중이라면?
  const comments = use(fetchComments()); // <--- 또는 여기서

  // ... 렌더링 로직
}

PostDetails가 렌더링되는 도중에, use(fetchPost())를 만났다고 가정합시다. 이 fetchPost Promise는 아직 처리 중(pending)입니다. 이때 use 훅은 무엇을 할까요?”

앤드류가 질문을 던졌다.

use 훅은 그 자리에서 특별한 종류의 에러, 정확히는 Promise 자체를 ‘던집니다(throw)’. 이것은 일반적인 자바스크립트 에러와는 다릅니다. React만이 이해할 수 있는 특별한 신호죠. ‘작업이 아직 끝나지 않았으니, 이 렌더링을 계속 진행할 수 없음’이라는 의미입니다.”

그의 설명에 따라 팀원들은 코드의 실행 흐름을 머릿속으로 따라갔다.

use 훅이 신호를 던지는 순간, PostDetails 컴포넌트의 실행은 즉시 중단된다. 그 아래에 있는 use(fetchComments())나 다른 렌더링 로직은 아예 실행될 기회조차 얻지 못한다.

그러면 React는 무엇을 하는가?

“React는 이 특별한 신호를 ‘잡습니다(catch)’. 그리고는 컴포넌트 트리를 거슬러 올라가기 시작합니다. 가장 가까운 <Suspense> 경계를 찾기 위해서죠.”

앤드류는 화이트보드의 PostDetails에서 바깥쪽으로 향하는 화살표를 그렸다. 화살표의 끝은 PostDetails를 직접 감싸고 있는 <Suspense fallback={<PostSkeleton />}>을 향했다.

“React는 가장 가까운 Suspense를 찾으면, 그곳에 정의된 fallback UI, 즉 <PostSkeleton />을 대신 렌더링합니다. 그리고 원래 렌더링하려던 PostDetails 작업은 잠시 보류해두죠.”

이것이 바로 둘의 관계였다.

  • use: “아직 준비 안 됐어!”라고 소리치며 작업을 중단시키는 현장 작업자.
  • Suspense: 그 소리를 듣고 달려와, 임시 안전 펜스(fallback)를 치고 상황을 정리하는 현장 관리자.

만약 PostDetails를 감싸는 Suspense가 없었다면, React는 트리를 더 거슬러 올라가 App 레벨에 있는 <Suspense fallback={<PageSpinner />}>를 찾아냈을 것이다. 어떤 fallback을 보여줄지는 가장 가까운 Suspense 경계가 결정한다. 이 예측 가능한 동작 덕분에 개발자는 로딩 UI의 범위를 매우 세밀하게 제어할 수 있었다.

use 훅은 단독으로 존재할 수 없었다. Suspense라는 파트너가 없다면, use가 던진 신호는 그저 처리되지 않은 에러로 남아 앱을 중단시킬 뿐이었다. 반대로 Suspense 역시 use 훅이나 React.lazy처럼 자신에게 신호를 보내줄 존재가 없다면 아무 의미 없는 빈 껍데기였다.

이 둘은 분리할 수 없는 한 몸이었다. 이 완벽한 파트너십을 통해, React는 비동기 로딩이라는 예측 불가능한 작업을, 선언적이고 구조적인 방식으로 완전히 정복해 나가고 있었다.