본문 바로가기
부트캠프

멋쟁이사자처럼 프론트엔드 부트캠프 14기 - Day 90 (Suspense 바운더리, 코드 분할(React.lazy))

by 나른한_꼬리_ 2025. 9. 16.
반응형

 

 

 

목차

 

 

Suspense 바운더리

Suspense는 리액트에서 비동기 데이터 로딩 상태를 쉽고 자연스럽게 관리할 수 있게 하는 기능이다. 기존에는 데이터를 불러올 때마다 isLoading과 error 같은 상태 변수를 만들고 조건문으로 로딩 UI에러 UI를 직접 관리해야 했다. 하지만 Suspense를 사용하면 동기 코드처럼 자연스럽게 비동기 데이터를 처리할 수 있고, 로딩 상태 관리 코드를 일일이 작성하지 않아도 돼서 컴포넌트가 훨씬 간결해진다.

 

Suspense는 리액트에서 기본적으로 제공하지만, 비동기 데이터 처리를 위해서는 Suspense를 지원하는 라이브러리나 프레임워크가 필요하다. 대표적으로 Next.js나 TanStack Query 등이 있다.

 

Suspense는 fallback이라는 속성으로 로딩 중일 떄 보여줄 UI를 지정할 수 있다. Suspense는 로딩 상태만 처리한다. 에러가 발생했을 때는 Error Boundary로 별도로 감싸야 한다.

 

 

코드 분할(React.lazy)

리액트로 웹 앱을 만들다 보면 점점 컴포넌트가 많아지고 코드가 커진다. 모든 코드를 한 번에 다운로드하면 사용자는 페이지를 여는 데 오랜 시간이 걸릴 수 있다. 불필요한 네트워크 자원을 낭비하고 초기 로딩 속도가 느려지면 사용자 경험(UX)이 떨어질 것이다.

 

이 문제를 해결하기 위해 리액트는 React.lazy와 Suspense 기능을 제공한다. React.lazy는 컴포넌트를 필요할 때 비동기로 불러올 수 있게 해준다. Suspense는 비동기로 불러온 컴포넌트가 준비될 때까지 보여줄 로딩 UI를 지정하는 역할을 한다. 따라서, React.lazy로 로드되는 컴포넌트는 반드시 Suspense로 감싸야 한다.

 

코드를 분할하면 다음과 같은 효과를 기대할 수 있다.

  • 불필요한 코드 다운로드 방지: 사용하지 않는 기능의 코드는 다운로드하지 않는다.
  • 빠른 초기 로딩: 진짜 필요한 코드만 먼저 받아와서 빠르게 보여줄 수 있다.
  • 네트워크 효율성 증가: 사용자의 행동에 맞춰 필요한 코드만 서버에서 받아온다.

 

동시 로딩과 Suspense

실제 서비스에서는 여러 개의 컴포넌트를 동시에 지연 로딩해야 할 때도 있다. 이때 Suspense를 어떻게 감싸느냐에 따라 로딩 UI의 작동 방식이 달라진다.

 

Suspense 하나로 감싸기

모든 컴포넌트가 모두 준비될 때까지 로딩 UI가 계속 표시되고, 컴포넌트 중 하나라도 늦게 로드되면 전체가 늦게 나타난다.

<Suspense fallback={<p role="status">로딩 중...</p>}>
  <NewComment />
  <Comments />
</Suspense>

 

별도 Suspense로 감싸기

각 컴포넌트가 개별적으로 로드되고, 먼저 준비되는 컴포넌트부터 보여준다. 아직 준비되지 않은 컴포넌트는 준비될 때까지 별도 로딩 UI를 노출한다.

<Suspense fallback={<p role="status">새 댓글 로딩 중...</p>}>
  <NewComment />
</Suspense>
<Suspense fallback={<p role="status">댓글 로딩 중...</p>}>
  <Comments />
</Suspense>

 

Suspense를 중첩해 감싸기

Suspense를 중첩해서 사용하면 먼저 보여줘야 하는 것과 나중에 보여줘도 되는 것을 유연하게 제어할 수 있다. 가장 바깥 Suspense는 전체 섹션이 준비되지 않았을 때 로딩 UI를 보여주고, 내부 Suspense는 각 컴포넌트가 개별적으로 준비될 때 로딩 UI를 보여준다.

 

 

React.lazy 주의 사항

React.lazy는 기본(default) 내보내기만 지원한다. 이름으로(named) 내보내기만 있는 모듈을 lazy로 불러오고 싶으면 아래와 같이 한 번 감싸서 default로 변환해야 한다.

const Comments = React.lazy(() =>
  import('./CommentsModule').then((module) => ({
    default: module.Comments
  }))
)

 

 

오늘 하루를 돌아보며

React.lazy와 Suspense는 둘이 한 세트다. Suspense를 혼자 사용할 수는 있지만 React.lazy를 사용하려면 Suspense도 같이 사용해야 한다. 둘을 사용하면 필요한 시점에만 컴포넌트를 네트워크로 받아와 초기 로딩 속도를 개선하고, 네트워크 효율성을 높일 수 있다. Suspense의 감싸는 방식에 따라 로딩 UI가달라지기 때문에 UX에 맞춰 잘 설계해야겠다. 특히 에러 처리와 export default 규칙의 유의해야겠다.

 

 

반응형