한국어

Suspense로 React의 효율적인 데이터 페칭을 경험하세요! 컴포넌트 수준 로딩부터 병렬 데이터 페칭까지 다양한 전략을 살펴보고, 반응형 사용자 친화적 애플리케이션을 구축하세요.

React Suspense: 최신 애플리케이션을 위한 데이터 페칭 전략

React Suspense는 React 16.6에 도입된 강력한 기능으로, 비동기 작업, 특히 데이터 페칭을 간단하게 처리할 수 있게 해줍니다. 데이터 로드를 기다리는 동안 컴포넌트 렌더링을 '일시 중단'하여 로딩 상태를 보다 선언적이고 사용자 친화적인 방식으로 관리할 수 있습니다. 이 가이드에서는 React Suspense를 사용한 다양한 데이터 페칭 전략을 살펴보고, 반응형 고성능 애플리케이션 구축에 대한 실용적인 통찰력을 제공합니다.

React Suspense 이해하기

구체적인 전략을 살펴보기 전에 React Suspense의 핵심 개념을 이해해 보겠습니다.

Suspense를 이용한 데이터 페칭 전략

React Suspense를 사용한 효과적인 데이터 페칭 전략 몇 가지를 소개합니다.

1. 컴포넌트 수준 데이터 페칭

이는 가장 간단한 접근 방식으로, 각 컴포넌트가 Suspense 경계 내에서 자체 데이터를 페칭합니다. 독립적인 데이터 요구 사항을 가진 간단한 컴포넌트에 적합합니다.

예시:

API에서 사용자 데이터를 가져와야 하는 UserProfile 컴포넌트가 있다고 가정해 보겠습니다.

// 간단한 데이터 페칭 유틸리티 (선호하는 라이브러리로 대체하세요)
const fetchData = (url) => {
  let status = 'pending';
  let result;
  let suspender = fetch(url)
    .then(res => {
      if (!res.ok) {
        throw new Error(`HTTP error! Status: ${res.status}`);
      }
      return res.json();
    })
    .then(
      res => {
        status = 'success';
        result = res;
      },
      err => {
        status = 'error';
        result = err;
      }
    );

  return {
    read() {
      if (status === 'pending') {
        throw suspender;
      } else if (status === 'error') {
        throw result;
      }
      return result;
    }
  };
};

const userResource = fetchData('/api/user/123');

function UserProfile() {
  const user = userResource.read();
  return (
    <div>
      <h2>{user.name}</h2>
      <p>Email: {user.email}</p>
    </div>
  );
}

function App() {
  return (
    <Suspense fallback={<div>사용자 데이터 로딩 중...</div>}>
      <UserProfile />
    </Suspense>
  );
}

설명:

장점:

단점:

2. 병렬 데이터 페칭

워터폴 페칭을 피하기 위해 여러 데이터 요청을 동시에 시작하고 Promise.all 또는 유사한 기술을 사용하여 모든 요청이 완료될 때까지 기다린 후 컴포넌트를 렌더링할 수 있습니다. 이는 전체 로딩 시간을 최소화합니다.

예시:

const userResource = fetchData('/api/user/123');
const postsResource = fetchData('/api/user/123/posts');

function UserProfile() {
  const user = userResource.read();
  const posts = postsResource.read();

  return (
    <div>
      <h2>{user.name}</h2>
      <p>Email: {user.email}</p>
      <h3>게시물:</h3>
      <ul>
        {posts.map(post => (<li key={post.id}>{post.title}</li>))}
      </ul>
    </div>
  );
}

function App() {
  return (
    <Suspense fallback={<div>사용자 데이터 및 게시물 로딩 중...</div>}>
      <UserProfile />
    </Suspense>
  );
}

설명:

장점:

단점:

3. 선택적 하이드레이션 (서버 사이드 렌더링 - SSR용)

서버 사이드 렌더링(SSR)을 사용할 때, Suspense를 사용하여 페이지의 일부를 선택적으로 하이드레이션할 수 있습니다. 즉, 페이지의 가장 중요한 부분을 먼저 하이드레이션하여 상호작용까지의 시간(Time to Interactive, TTI)과 체감 성능을 향상시킬 수 있습니다. 이는 기본 레이아웃이나 핵심 콘텐츠를 최대한 빨리 보여주고 덜 중요한 컴포넌트의 하이드레이션은 지연시키고 싶을 때 유용합니다.

예시 (개념적):

// 서버 측:
<Suspense fallback={<div>중요 콘텐츠 로딩 중...</div>}>
  <CriticalContent />
</Suspense>
<Suspense fallback={<div>선택적 콘텐츠 로딩 중...</div>}>
  <OptionalContent />
</Suspense>

설명:

장점:

단점:

4. Suspense를 지원하는 데이터 페칭 라이브러리

몇몇 인기 있는 데이터 페칭 라이브러리는 React Suspense를 내장 지원합니다. 이러한 라이브러리는 데이터를 페칭하고 Suspense와 통합하는 더 편리하고 효율적인 방법을 제공합니다. 주목할 만한 예는 다음과 같습니다.

예시 (SWR 사용):

import useSWR from 'swr'

const fetcher = (...args) => fetch(...args).then(res => res.json())

function UserProfile() {
  const { data: user, error } = useSWR('/api/user/123', fetcher, { suspense: true })

  if (error) return <div>로딩 실패</div>
  if (!user) return <div>로딩 중...</div> // Suspense 사용 시 이 부분은 거의 렌더링되지 않습니다

  return (
    <div>
      <h2>{user.name}</h2>
      <p>Email: {user.email}</p>
    </div>
  )
}

function App() {
  return (
    <Suspense fallback={<div>사용자 데이터 로딩 중...</div>}>
      <UserProfile />
    </Suspense>
  );
}

설명:

장점:

단점:

Suspense를 이용한 오류 처리

Suspense를 사용할 때 오류 처리는 매우 중요합니다. React는 Suspense 경계 내에서 발생하는 오류를 잡기 위해 ErrorBoundary 컴포넌트를 제공합니다.

예시:

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    // 다음 렌더링에서 폴백 UI가 표시되도록 상태를 업데이트합니다.
    return { hasError: true };
  }

  componentDidCatch(error, errorInfo) {
    // 오류 보고 서비스에 오류를 기록할 수도 있습니다
    console.error(error, errorInfo);
  }

  render() {
    if (this.state.hasError) {
      // 원하는 커스텀 폴백 UI를 렌더링할 수 있습니다
      return <h1>문제가 발생했습니다.</h1>;
    }

    return this.props.children; 
  }
}

function App() {
  return (
    <ErrorBoundary>
      <Suspense fallback={<div>로딩 중...</div>}>
        <UserProfile />
      </Suspense>
    </ErrorBoundary>
  );
}

설명:

React Suspense 사용을 위한 모범 사례

실제 사례

React Suspense는 다음과 같은 다양한 시나리오에 적용될 수 있습니다.

사례 1: 국제 전자상거래 플랫폼

다양한 국가의 고객에게 서비스를 제공하는 전자상거래 플랫폼을 상상해 보세요. 가격 및 설명과 같은 상품 세부 정보는 사용자의 위치에 따라 가져와야 할 수 있습니다. Suspense를 사용하여 지역화된 상품 정보를 가져오는 동안 로딩 표시기를 표시할 수 있습니다.

function ProductDetails({ productId, locale }) {
  const productResource = fetchData(`/api/products/${productId}?locale=${locale}`);
  const product = productResource.read();

  return (
    <div>
      <h2>{product.name}</h2>
      <p>가격: {product.price}</p>
      <p>설명: {product.description}</p>
    </div>
  );
}

function App() {
  const userLocale = getUserLocale(); // 사용자의 로케일을 결정하는 함수
  return (
    <Suspense fallback={<div>상품 상세 정보 로딩 중...</div>}>
      <ProductDetails productId="123" locale={userLocale} />
    </Suspense>
  );
}

사례 2: 글로벌 소셜 미디어 피드

전 세계 사용자의 게시물 피드를 표시하는 소셜 미디어 플랫폼을 생각해 보세요. 각 게시물에는 텍스트, 이미지, 비디오가 포함될 수 있으며, 로드하는 데 걸리는 시간이 다를 수 있습니다. Suspense를 사용하여 개별 게시물의 콘텐츠가 로드되는 동안 플레이스홀더를 표시하여 더 부드러운 스크롤 경험을 제공할 수 있습니다.

function Post({ postId }) {
  const postResource = fetchData(`/api/posts/${postId}`);
  const post = postResource.read();

  return (
    <div>
      <p>{post.text}</p>
      {post.image && <img src={post.image} alt="게시물 이미지" />}
      {post.video && <video src={post.video} controls />}
    </div>
  );
}

function App() {
  const postIds = getPostIds(); // 포스트 ID 목록을 가져오는 함수
  return (
    <div>
      {postIds.map(postId => (
        <Suspense key={postId} fallback={<div>게시물 로딩 중...</div>}>
          <Post postId={postId} />
        </Suspense>
      ))}
    </div>
  );
}

결론

React Suspense는 React 애플리케이션에서 비동기 데이터 페칭을 관리하는 강력한 도구입니다. 다양한 데이터 페칭 전략과 모범 사례를 이해함으로써 훌륭한 사용자 경험을 제공하는 반응형, 사용자 친화적, 고성능 애플리케이션을 구축할 수 있습니다. 특정 요구에 가장 적합한 접근 방식을 찾기 위해 다양한 전략과 라이브러리를 실험해 보세요.

React가 계속 발전함에 따라 Suspense는 데이터 페칭 및 렌더링에서 훨씬 더 중요한 역할을 할 가능성이 높습니다. 최신 개발 동향과 모범 사례에 대한 정보를 지속적으로 파악하면 이 기능의 잠재력을 최대한 활용하는 데 도움이 될 것입니다.