> 웹 프론트엔드 > JS 튜토리얼 > React Native/ReactJS의 지연 로딩 개념 마스터하기

React Native/ReactJS의 지연 로딩 개념 마스터하기

DDD
풀어 주다: 2024-09-18 15:27:49
원래의
915명이 탐색했습니다.

Lazy Loading은 리소스가 필요할 때만 로드되는 디자인 패턴입니다. 이는 React Native 애플리케이션의 초기 로드 시간을 개선하고 메모리 소비를 줄이며 전반적인 성능을 향상시키는 데 도움이 됩니다.

Master lazy loading concept in React Native/ReactJS

왜 지연 로딩인가?

  1. 성능 최적화: 앱 초기 실행 시 불필요한 리소스의 로딩을 방지하여 로딩 시간을 대폭 줄일 수 있습니다.
  2. 메모리 사용량 감소: 지연 로딩은 필요하지 않을 때 이미지, 구성 요소 또는 외부 라이브러리와 같은 대규모 리소스를 메모리에 유지하는 것을 방지합니다.
  3. 향상된 사용자 경험: 요청 시 리소스를 로드하면 더욱 원활한 탐색 및 상호 작용이 가능합니다.

1) React Native 화면/컴포넌트의 지연 로딩 사용 사례

  1. 지연 로딩 화면(코드 분할):
    React Native에서 지연 로딩은 일반적으로 구성 요소에 사용되며, 특히 사용자가 자주 방문하지 않을 수 있는 다른 화면이 있는 경우에는 더욱 그렇습니다. 이러한 화면을 느리게 로드하면 초기 번들 크기가 줄어듭니다.

  2. React.lazy() 및 Suspense를 사용한 지연 로딩:
    React는 구성 요소의 지연 로딩을 활성화하기 위해 React.lazy() 함수를 도입했습니다. 지연 로딩을 사용하려면 구성 요소가 로드될 때까지 Suspense를 대체 수단으로 사용합니다.

일반 사용법

일반적인 사용에서는 앱이 시작될 때 모든 리소스, 구성 요소, 라이브러리 및 데이터가 미리 로드됩니다. 이 접근 방식은 소규모 애플리케이션에는 적합하지만 앱이 성장함에 따라 비효율적이고 리소스 집약적이어서 성능과 로드 시간에 영향을 미칠 수 있습니다.

예: 일반 구성요소 로딩

import React from 'react';
import HomeScreen from './screens/HomeScreen';
import ProfileScreen from './screens/ProfileScreen';

const App = () => {
  return (
    <>
      <HomeScreen />
      <ProfileScreen />
    </>
  );
};

export default App;
로그인 후 복사

설명:

  • 이 예에서는 사용자가 탐색하는지 여부에 관계없이 HomeScreen 및 ProfileScreen 구성 요소를 모두 가져오고 미리 로드합니다.
  • 이렇게 하면 모든 구성 요소가 한 번에 번들로 로드되기 때문에 초기 로드 시간이 늘어납니다.

지연 로딩 사용법

지연 로딩을 사용하면 필요할 때만 구성 요소, 라이브러리 또는 데이터가 로드됩니다. 필요한 리소스만 요청 시 로드되므로 초기 로드 시간과 메모리 사용량이 줄어들어 성능이 향상됩니다.

예: 지연 로딩 구성 요소

import React, { Suspense, lazy } from 'react';
import { ActivityIndicator } from 'react-native';

const HomeScreen = lazy(() => import('./screens/HomeScreen'));
const ProfileScreen = lazy(() => import('./screens/ProfileScreen'));

const App = () => {
  return (
    <Suspense fallback={<ActivityIndicator size="large" color="#0000ff" />}>
      <HomeScreen />
      <ProfileScreen />
    </Suspense>
  );
};

export default App;
로그인 후 복사

설명:

  • 이 예에서는 HomeScreen과 ProfileScreen이 React.lazy()를 사용하여 지연 로드됩니다.
  • 이러한 구성요소가 로드될 때까지 대체(ActivityIndicator)가 표시됩니다.
  • 구성요소가 렌더링될 때만 로드되므로 앱의 초기 로드 시간이 단축됩니다.

일반 로딩과 지연 로딩의 차이점

기능 일반적인 사용법 지연 로딩
Feature Normal Usage Lazy Loading
Loading Strategy Everything is loaded upfront when the app starts. Components, resources, or data are loaded only when needed.
Initial Load Time Higher, as all resources are loaded at once. Lower, as only essential components are loaded upfront.
Memory Usage Higher, as all components and resources are loaded into memory. Lower, as only necessary components are loaded into memory.
User Experience Slower startup but smoother transitions once loaded. Faster startup but slight delay when loading resources.
Best for Small applications with limited components. Large applications where not all components are used initially.
Implementation Simpler, as everything is bundled at once. Requires managing dynamic imports and possibly loading states.
전략 로딩 앱이 시작될 때 모든 것이 미리 로드됩니다. 구성요소, 리소스 또는 데이터는 필요할 때만 로드됩니다. 초기 로딩 시간 모든 리소스가 동시에 로드되므로 더 높습니다. 필수 구성요소만 미리 로드되므로 더 낮습니다. 메모리 사용량 모든 구성 요소와 리소스가 메모리에 로드되므로 더 높습니다. 필요한 구성요소만 메모리에 로드되므로 더 낮습니다. 사용자 경험 시작은 느리지만 로드된 후에는 전환이 더 매끄러워집니다. 시작 속도는 빨라지지만 리소스 로드 시 약간의 지연이 발생합니다. 최적의 용도 제한된 구성 요소를 갖춘 소규모 애플리케이션. 처음에 모든 구성요소가 사용되지 않는 대규모 애플리케이션. 구현 모든 것이 한 번에 번들로 제공되므로 더 간단합니다. 동적 가져오기 및 로드 상태 관리가 필요합니다.

2. Lazy Loading in Navigation (React Navigation):

Lazy loading ensures that screens or components are only mounted when they are accessed (when the user navigates to them), thus improving performance, especially in apps with multiple screens.

Example: Lazy Loading in React Navigation (Stack Navigator)

import React, { Suspense, lazy } from 'react';
import { createStackNavigator } from '@react-navigation/stack';
import { NavigationContainer } from '@react-navigation/native';
import { ActivityIndicator } from 'react-native';

// Lazy load screens
const HomeScreen = lazy(() => import('./screens/HomeScreen'));
const ProfileScreen = lazy(() => import('./screens/ProfileScreen'));

const Stack = createStackNavigator();

const App = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator>
        <Stack.Screen
          name="Home"
          component={() => (
            <Suspense fallback={<ActivityIndicator size="large" color="#0000ff" />}>
              <HomeScreen />
            </Suspense>
          )}
        />
        <Stack.Screen
          name="Profile"
          component={() => (
            <Suspense fallback={<ActivityIndicator size="large" color="#0000ff" />}>
              <ProfileScreen />
            </Suspense>
          )}
        />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

export default App;
로그인 후 복사

Explanation:

  • In this example, the HomeScreen and ProfileScreen components are lazily loaded using React.lazy().
  • The Suspense component provides a loading indicator (ActivityIndicator) while the components are being loaded.
  • Screens will only load when the user navigates to them, reducing the initial load time.

3. Lazy Loading Images :

In React Native, lazy loading can be achieved using libraries like react-native-fast-image or manually handling image loading by tracking visibility with tools like IntersectionObserver.

a) Using react-native-fast-image

react-native-fast-image is a performant image component that provides built-in lazy loading.

npm install react-native-fast-image
로그인 후 복사

Example: Lazy Loading Images with react-native-fast-image

import React from 'react';
import { View, ScrollView, Text } from 'react-native';
import FastImage from 'react-native-fast-image';

const LazyLoadingImages = () => {
  return (
    <ScrollView>
      <Text>Scroll down to load images</Text>
      <FastImage
        style={{ width: 200, height: 200 }}
        source={{
          uri: 'https://example.com/my-image1.jpg',
          priority: FastImage.priority.normal,
        }}
        resizeMode={FastImage.resizeMode.contain}
      />
      <FastImage
        style={{ width: 200, height: 200 }}
        source={{
          uri: 'https://example.com/my-image2.jpg',
          priority: FastImage.priority.normal,
        }}
        resizeMode={FastImage.resizeMode.contain}
      />
    </ScrollView>
  );
};

export default LazyLoadingImages;
로그인 후 복사

Explanation:

  • The FastImage component from react-native-fast-image helps with lazy loading. It loads images only when they are about to be displayed.
  • It also provides efficient caching and priority options, improving performance.

b) Manual Lazy Loading (Visibility Tracking)

In cases where you don't want to use a third-party library, you can implement lazy loading by tracking when an image enters the viewport using tools like IntersectionObserver (web) or a custom scroll listener in React Native.

Example: Lazy Loading with Visibility Tracking (using React Native)

import React, { useState, useEffect } from 'react';
import { View, Image, ScrollView } from 'react-native';

const LazyImage = ({ src, style }) => {
  const [isVisible, setIsVisible] = useState(false);

  const onScroll = (event) => {
    // Implement logic to determine if image is visible based on scroll position
    const { y } = event.nativeEvent.contentOffset;
    if (y > 100) { // Example: load image when scrolled past 100px
      setIsVisible(true);
    }
  };

  return (
    <ScrollView onScroll={onScroll} scrollEventThrottle={16}>
      <View>
        {isVisible ? (
          <Image source={{ uri: src }} style={style} />
        ) : (
          <View style={style} />
        )}
      </View>
    </ScrollView>
  );
};

const App = () => {
  return (
    <LazyImage src="https://example.com/my-image.jpg" style={{ width: 200, height: 200 }} />
  );
};

export default App;
로그인 후 복사

Explanation:

  • The LazyImage component only loads the image once the user has scrolled a certain amount (onScroll event).
  • This approach manually tracks the scroll position and loads the image accordingly.

4. Lazy Loading with Redux (Dynamic Reducers) :

When using Redux, you may want to lazy load certain reducers only when necessary, such as for specific screens or features.

  1. Create a function to inject reducers dynamically.
  2. Add the new reducer to the Redux store when needed (e.g., when a user navigates to a new screen).
  3. Remove the reducer when it is no longer needed (optional).

Example: Lazy Loading Reducers in a React Application with Redux

1. Initial Redux Store Setup

Start by setting up a standard Redux store, but instead of adding all reducers upfront, create an injection method.

import { configureStore, combineReducers } from '@reduxjs/toolkit';

const staticReducers = {
  // Add reducers that are needed from the start
};

export const createReducer = (asyncReducers = {}) => {
  return combineReducers({
    ...staticReducers,
    ...asyncReducers,
  });
};

const store = configureStore({
  reducer: createReducer(),
});

// Store injected reducers here
store.asyncReducers = {};

export default store;
로그인 후 복사

In the above code:

  • staticReducers: Contains reducers that are loaded when the app starts.
  • asyncReducers: This object will contain dynamically injected reducers as they are loaded.

2. Dynamic Reducer Injection Method

Create a helper function to inject new reducers dynamically into the store.

// Helper function to inject a new reducer dynamically
export function injectReducer(key, asyncReducer) {
  if (!store.asyncReducers[key]) {
    store.asyncReducers[key] = asyncReducer;
    store.replaceReducer(createReducer(store.asyncReducers));
  }
}
로그인 후 복사

The injectReducer function checks if a reducer has already been added. If not, it injects it into the store and replaces the current root reducer.

3. Loading Reducer When Needed (Lazy Loading)

Imagine you have a new page or feature that needs its own reducer. You can inject the reducer dynamically when this page is loaded.

import { lazy, Suspense, useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { injectReducer } from './store';
import featureReducer from './features/featureSlice'; // The reducer for this feature

const FeatureComponent = lazy(() => import('./components/FeatureComponent'));

const FeaturePage = () => {
  const dispatch = useDispatch();

  useEffect(() => {
    injectReducer('feature', featureReducer); // Dynamically load the reducer
  }, [dispatch]);

  return (
    <Suspense fallback={<div>Loading...</div>}>
      <FeatureComponent />
    </Suspense>
  );
};

export default FeaturePage;
로그인 후 복사

Here:

  • When the FeaturePage component is loaded, the injectReducer function adds the featureReducer dynamically to the Redux store.
  • The Suspense component handles lazy loading of the FeatureComponent.

4. Feature Reducer Example

The reducer for the feature is written as usual, using Redux Toolkit.

import { createSlice } from '@reduxjs/toolkit';

const featureSlice = createSlice({
  name: 'feature',
  initialState: { data: [] },
  reducers: {
    setData: (state, action) => {
      state.data = action.payload;
    },
  },
});

export const { setData } = featureSlice.actions;
export default featureSlice.reducer;
로그인 후 복사

Removing a Reducer (Optional)

You might want to remove a reducer when it's no longer needed, for example, when navigating away from a page.

Here’s how you can remove a reducer:

export function removeReducer(key) {
  if (store.asyncReducers[key]) {
    delete store.asyncReducers[key];
    store.replaceReducer(createReducer(store.asyncReducers));
  }
}
로그인 후 복사

You can call this function when a feature or page is unmounted to remove its reducer from the store.


5. Lazy Loading Libraries/Packages:

If you are using heavy third-party libraries, lazy loading them can help optimize performance.

   import React, { useState } from 'react';

   const HeavyComponent = React.lazy(() => import('heavy-library')); // React.lazy(() => import('moment'))

   const App = () => {
     const [showComponent, setShowComponent] = useState(false);

     return (
       <View>
         <Button title="Load Heavy Component" onPress={() => setShowComponent(true)} />
         {showComponent && (
           <Suspense fallback={<Text>Loading...</Text>}>
             <HeavyComponent />
           </Suspense>
         )}
       </View>
     );
   };
로그인 후 복사
  1. Lazy Loading Data: You can also implement lazy loading for data fetching, where data is fetched in chunks or when a user scrolls (infinite scroll).

Example: Lazy Loading Data:

   import React, { useState, useEffect } from 'react';
   import { FlatList, ActivityIndicator, Text } from 'react-native';

   const LazyLoadData = () => {
     const [data, setData] = useState([]);
     const [loading, setLoading] = useState(true);

     useEffect(() => {
       fetch('https://api.example.com/data')
         .then(response => response.json())
         .then(json => {
           setData(json);
           setLoading(false);
         });
     }, []);

     if (loading) {
       return <ActivityIndicator />;
     }

     return (
       <FlatList
         data={data}
         renderItem={({ item }) => <Text>{item.name}</Text>}
         keyExtractor={item => item.id}
       />
     );
   };

   export default LazyLoadData;
로그인 후 복사

Explanation:

  • Fetching data lazily ensures that the app doesn’t load too much data at once, improving performance and reducing bandwidth usage.

Summary of Use Cases:

  1. Screens/Components: Lazy loading React Native screens or components using React.lazy() and Suspense.
  2. Images: Lazy loading images as they enter the viewport to save memory and bandwidth.
  3. Redux Reducers: Injecting reducers dynamically to reduce the initial store size in Redux.
  4. Libraries: Lazily load third-party libraries or packages to reduce the initial bundle size.
  5. Data: Implement lazy loading for large datasets using techniques like pagination or infinite scrolling.

Lazy loading helps improve the performance, memory usage, and user experience of your React Native app, making it more efficient and responsive for users.

위 내용은 React Native/ReactJS의 지연 로딩 개념 마스터하기의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿