-
[React] Suspense로 로딩 쉽게 구현하기SPA/React.js 2024. 8. 10. 19:54
React Suspense는 비동기 데이터 로딩을 쉽게 관리할 수 있도록 해주는 기능이다.
이번 글에서는 React Suspense의 개념과 사용 방법 및 활용 방법에 대해 다뤄보고자 한다.
1. React Suspense란?
React Suspense는 React에 내장되어 있는 기능으로, 비동기 데이터를 처리하는 방법을 단순화하고 사용자 경험을 개선하기 위해 도입된 기능이다.
우리가 개발을 진행하다 보면 데이터 로딩 속도로 인해 첫 화면이 렌더링되는 데 시간이 오래 걸릴 때가 있다.
이는 사용자 경험 저하로 이어지기에 이런 문제를 개선하는 것은 중요한데 이런 상황에서 React Suspense를 사용하면 이 문제를 쉽게 해결할 수 있다.
2. 사용방법
Suspense를 사용하는 방법은 매우 간단하다,.
Suspense를 import하고 Suspense 컴포넌트로 처리할 컴포넌트를 감싸면 된다.
import React, { Suspense } from 'react'; const FeedFavoriteScreen = () => { return ( <SafeAreaView style={styles.container}> <Suspense fallback={<Loader/>}> <FeedFavoriteList/> </Suspense> </SafeAreaView> ) }
위의 코드에서 Suspense 컴포넌트는 FeedFavoriteList가 비동기 작업을 수행하는 동안 사용자에게 Loader 컴포넌트를 표시하며
FeedFavoriteList가 데이터를 모두 불러오면 Suspense는 로딩 상태를 해제하고 FeedFavoriteList 컴포넌트를 렌더링하게 된다.
3. fallback과 lazy
React Suspense에서 핵심적인 개념은 fallback과 lazy이다.
(1) fallback
fallback은 Suspense가 비동기 작업이 완료되기를 기다리는동안 보여줄 UI를 정의한다.
보통 로딩 스피너, 스켈레톤 UI 등을 활용할 수 있다.
위 예시에서 사용한 Loader 컴포넌트는 커스텀 컴포넌트로,
아래와 같이 일반적으로 컴포넌트를 만들듯이 생성하고 fallback에서 불러오면 된다.
import { colors } from '@/constants'; import React, { PropsWithChildren, ReactNode } from 'react'; import {ActivityIndicator, StyleSheet, View} from 'react-native'; interface LoaderProps { children?: ReactNode; size?: number | 'small' | 'large' | undefined; color?: string; } function Loader({ children, size = 'small', color = colors.light.GRAY_500, ...props }: PropsWithChildren<LoaderProps>) { return ( <View style={styles.container}> <ActivityIndicator size={size} color={color} style={styles.indicator} {...props} /> {children} </View> ) } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', }, indicator: { marginBottom: 20, } }); export default Loader;
이렇듯 보여지는 UI가 정해져 있지 않고 원하는 모양의 로딩중 UI를 제작하고 Suspense를 통해 쉽게 적용할 수 있다는 것도 장점이다.
(2) lazy
Suspense는 React lazy와 함께 주로 사용되는데 React lazy는 동적으로 컴포넌트를 가져와서 코드 분할(Code Splitting)을 쉽게 구현할 수 있도록 도와준다.
import React, { Suspense, lazy } from 'react'; const MyAsyncComponent = lazy(() => import('./FeedFavoriteList')); const FeedFavoriteScreen = () => { return ( <SafeAreaView style={styles.container}> <Suspense fallback={<Loader/>}> <MyAsyncComponent/> </Suspense> </SafeAreaView> ); }
위 예제에서는 React lazy를 사용해 MyAsyncComponent를 동적으로 가져온다.
이 때 컴포넌트가 로드될 때까지는 fallback에 정의된 컴포넌트가 화면에 표시된다.
4. 다른 활용 방법
그 외에도 Suspense는 비동기 데이터 페칭, 서버 사이드 렌더링, 에러 처리 시에 사용할 수 있다.
(1) 비동기 데이터 페칭
React 18부터 비동기 데이터 페칭에서 Suspense를 사용할 수 있는 기능이 강화되었는데
useEffect를 이용해 데이터를 가져오는 게 아닌, Suspense를 활용하여 가져올 수 있게 됐다.
(2) 서버 사이드 렌더링
React 18부터는 서버 사이드에서 비동기 데이터 페팅을 처리할 수 있으며, 클라이언트는 데이터가 로드된 상태로 렌더링된 HTML을 받을 수 있다.
이는 초기 로딩 시간을 줄이고 사용자 경험을 개선하는 데 큰 도움을 준다.
(3) 에러 처리
react-error-boundary와 함께 사용함으로써 로딩 중 에러 발생 시 사용자에게 피드백을 제공하며 다른 부분은 정상적으로 동작하도록 할 수 있다.
import Loader from '@/components/common/Loader'; import RetryErrorBoundary from '@/components/common/RetryErrorBoundary'; import FeedList from '@/components/feed/FeedList'; import React, { Suspense } from 'react'; const FeedHomeScreen = () => { return ( <SafeAreaView style={styles.container}> <RetryErrorBoundary> <Suspense fallback={<Loader/>}> <FeedList/> </Suspense> </RetryErrorBoundary> </SafeAreaView> ) }
위 예제에서 사용한 RetryErrorBoundary는 RetryErrorBoundary 라이브러리를 활용하여 만든 커스텀 컴포넌트이다.
Suspense로 로딩 중일 때의 UI를 보여주며, 에러가 발생했을 시에는 RetryErrorBoundary 컴포넌트가 보여지도록 하는 것이다.
이를 통해 사용자는 현재 에러가 발생했다는 것을 알고 다시 시도해볼 수 있으며, 에러로 인한 사이드 이펙트로 다른 화면이 안 보여지게 될 가능성을 없앨 수 있다.
이렇게 React Suspense에 대해 알아보았는데
React Suspense를 활용해 코드의 복잡성을 줄이고 사용자에게 더 나은 경험을 제공할 수 있다는 점에서 큰 장점이 있다.
하지만 더 효율적이고 유지보수가 용이하게 하기 위해서는 React Suspense에 대해 제대로 이해하고 활용하는 게 중요할 것 같다.
[참고]
https://www.elancer.co.kr/blog/view?seq=267
'SPA > React.js' 카테고리의 다른 글
[React] JSX, 가상 dom과 리액트 파이버 (1) 2024.10.19 [React] QueryClient로 효과적인 서버 관리하기 (2) 2024.10.04 [React] useMutation 알아보기_(React Query, TanStack Query) (0) 2024.07.21 [React] Firebase로 게시물 카테고리별로 정렬하기 (0) 2022.11.22 [React] Firebase로 카테고리 생성 및 적용하기 (0) 2022.11.11