React Suspense에 대해서 알아보기

해니니·2024년 12월 21일
0
post-thumbnail

리액트 프로젝트를 진행하다가 보면 프론트엔드 개발에서 사용자가 어떻게 편하게 웹앱을 이용할 수 있을 지 UX를 고려한 다양한 기술 접근 방식을 공부하게 된다.

그 중에서 알게 된 개념 중에 하나가 Suspense 였고 아직은 실무에서나 프로젝트에서는 사용해본 적은 없지만 한번 정리해보고자 이 글을 써본다.
차차 프로젝트에서도 적용 해보면서 공부를 더 해봐야지!🍀


React Suspense란 무엇인가?

React에서 비동기 작업을 처리하면서 로딩 중에도 매끄러운 화면을 보여주는 기능이다.

비동기 작업을 하면 화면이 멈추거나 로딩 상태가 생길 수 있다.
Suspense는 로딩 상태를 관리해 사용자 경험(UX)을 더 편리하게 만든다.

데이터를 불러오는 동안 "로딩 중..."과 같은 화면을 표시하거나, 필요한 컴포넌트를 나중에 불러와 초기 로딩 속도를 개선하는 데 활용된다.

Suspense는 React 16.6에서 화면 나누기(Code Splitting) 기능으로 처음 도입되었고, React 18부터는 데이터 불러오기와 같은 더 다양한 기능을 지원하게 되었다.


React Suspense의 주요 특징

Suspense의 주요 특징은 다음과 같다.

Fallback UI 제공

Suspense는 데이터를 불러오거나 화면을 로드하는 동안 로딩 상태를 사용자에게 보여준다. fallback 속성을 사용해 "로딩 중..."과 같은 화면을 간단히 추가할 수 있다.

React.lazy

Suspense는 React.lazy와 함께 사용되어, 필요한 컴포넌트만 나중에 불러올 수 있다.
이렇게 하면 앱이 처음 실행될 때 더 빠르게 열리게 된다.

데이터 페칭 확장

React 18 이후로 Suspense는 데이터를 불러오는 작업에도 활용 가능하다.
네트워크 요청이 길어질 경우 로딩 화면을 보여주고 요청이 끝나면 결과를 표시한다.

Concurrent Features와의 조합

여러 작업이 동시에 일어날 때도 화면 전환이 끊기지 않도록 부드러운 사용자 경험을 제공한다.


Suspense의 기본 사용법

코드 스플리팅(Code Splitting) 예제

아래는 React.lazy와 Suspense를 사용해 컴포넌트를 필요한 순간에만 불러오는 예제다.

import React, { Suspense } from "react";

const LazyComponent = React.lazy(() => import('./LazyComponent'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </Suspense>
  );
}

Suspense로 데이터 로딩

Suspense는 비동기 작업을 처리하며, 로딩 상태에서 fallback UI를 보여주고 데이터가 준비되면 화면을 업데이트한다.

import React, { Suspense } from "react";

// 데이터를 비동기로 가져오는 함수
const fetchData = () => {
  return new Promise((resolve) => {
    setTimeout(() => resolve("Hello, Suspense!"), 2000); // 2초 후 데이터 반환
  });
};

// 데이터 로드 상태를 관리하는 리소스 객체
const resource = {
  data: fetchData(), // fetchData 호출로 Promise 저장
  read() {
    // 데이터가 아직 준비되지 않았으면 Suspense에 의해 대기 상태로 전환
    if (!this.data) {
      throw this.data;
    }
    // 데이터가 준비되었으면 반환
    return this.data;
  },
};

// 데이터를 화면에 표시하는 컴포넌트
function DataComponent() {
  const data = resource.read(); // 데이터가 준비되었는지 확인
  return <div>{data}</div>; // 데이터가 로드되면 화면에 표시
}

// App 컴포넌트에서 Suspense를 사용하여 로딩 상태와 데이터를 렌더링
function App() {
  return (
    <Suspense fallback={<div>Loading data...</div>}>
      <DataComponent />
    </Suspense>
  );
}

export default App;

Suspense와 동시성 기능(Concurrent Features)

React 18에서 추가된 Concurrent Features(동시성 기능)는 화면 전환을 더 부드럽게 만들어 사용자가 끊김 없는 경험을 하도록 돕는다.

Concurrent Mode란?

Concurrent Mode는 React에서 화면을 더 자연스럽게 업데이트하도록 돕는 기능이다.
중요한 작업은 먼저 처리하고, 덜 중요한 작업은 나중에 처리한다.

Suspense와 함께 사용하면 이런 장점이 있다.

- 중단 가능한 렌더링
화면을 바꾸는 중에도 중요한 작업(예: 사용자 입력)을 먼저 처리하고, 나머지는 잠시 멈췄다가 다시 진행할 수 있다.

- Fallback 렌더링 최적화
화면이 비어 있지 않게 "로딩 중..." 같은 메시지를 적절히 보여준다.

- 동적 우선순위 처리
중요한 작업부터 먼저 처리하고 덜 중요한 작업은 나중에 처리한다.


Suspense를 활용한 비동기 데이터 처리

React 18부터 Suspense는 데이터 페칭에도 사용할 수 있게 개선되었다.

다만 React 자체적으로 데이터 페칭을 제공하지 않으므로 Relay, SWR, React Query 같은 라이브러리와 함께 사용하는 경우가 많다.

React 18의 use 함수 사용

React 18의 use 함수를 사용하면 Suspense와 데이터 페칭을 결합할 수 있다.

const fetchData = async () => {
  const response = await fetch('/api/data');
  return response.json();
};

function DataComponent() {
  const data = use(fetchData());
  return <div>{data.message}</div>;
}

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <DataComponent />
    </Suspense>
  );
}

Suspense의 한계 및 주의사항

모든 비동기 작업을 지원하지 않음

Suspense는 Promise 기반의 비동기 작업만 처리할 수 있다.
따라서 데이터를 불러오거나 비동기 작업을 수행하려면 반드시 Promise 형태로 구현해야 한다.

주로 React Query, SWR, Relay 같은 데이터 가져오기 라이브러리와 함께 사용된다.
하지만 WebSocket처럼 지속적으로 연결이 필요한 작업은 Suspense로 처리할 수 없으므로, 추가적인 코드를 작성해야 한다.

초기 렌더링 지연 가능성

Suspense를 과도하게 사용하면 화면 로딩 중 기다리는 시간이 길어져 앱의 초기 로딩 속도가 느려질 수 있다. 이는 사용자 경험(UX)에 부정적인 영향을 미칠 수 있다.

이를 방지하려면 다음을 고려해야 한다.

  • 중요한 UI 요소(예: 헤더, 네비게이션 바)는 Suspense로 감싸지 않는다.
  • 데이터 로딩 속도를 최대한 빠르게 한다.
  • 덜 중요한 요소만 나중에 로드되도록 설정한다.

React 18 이상에서 더 강력해짐

React 18 이전에는 Suspense가 주로 코드 나누기(Code Splitting) 용도로만 사용됐다.
그러나 React 18부터는 데이터 페칭과 같은 작업도 지원하며, Concurrent Features를 활용해 더 부드럽고 효율적인 화면 전환을 제공한다.

예를 들어, React 18의 새로운 use API를 사용하면 Promise로 데이터를 가져온 뒤 Suspense와 간단히 연결할 수 있다.


결론

React Suspense는 화면 로딩과 비동기 작업을 효과적으로 관리할 수 있는 강력한 도구다.
화면을 나눠서 로드하거나 데이터를 불러오고, 이미지를 로드할 때 활용하면 사용자 경험을 크게 개선할 수 있다.

다만, 초기 로딩 속도나 적용 방식을 잘 계획해야 최상의 결과를 얻을 수 있다.
Relay나 SWR 같은 도구와 함께 사용하면 더 좋은 성능으로 쓸 수 있고 Concurrent Features와 조합하면 화면 전환이 더욱 부드럽다.

그동안 로딩 상태를 단순히 아래와 같이 처리했지만, Suspense를 사용하면 복잡한 환경에서도 로딩 상태를 더 효율적으로 관리할 수 있다는 것을 알게 되었다..!

{loading && <p>로딩 중...</p>}

Suspense를 실제 프로젝트에 적용해 리팩토링을 시도해 보고, 이를 기반으로 블로그에 정리해보는 시간도 가져야지.. 개발의 세계란 정말 무궁무진해...


참고한 사이트들
https://refine.dev/blog/react-suspense-guide/

profile
Front.Dev 연습생

0개의 댓글

관련 채용 정보