안녕하세요! 이번 글에서는 React Native에서 네트워크 요청을 최적화하는 방법을 다뤄보겠습니다.
처음에는 API 요청을 그냥 fetch나 axios로 하면 끝이라고 생각했어요.
작은 프로젝트에서는 큰 문제가 없었죠.
그런데 앱이 커지고 네트워크 요청이 많아지면서, 로딩 속도가 느려지거나 같은 데이터를 여러 번 요청하는 비효율적인 상황이 생겼어요.
특히, 사용자가 스크롤을 빠르게 내릴 때마다 새로운 요청이 발생하거나, 네트워크가 불안정할 때 앱이 멈추는 문제도 경험했어요.
그래서 이번 글에서는 네트워크 요청을 최적화하는 다양한 방법(캐싱, 로딩 처리, 성능 개선)을 정리해보겠습니다.
1. 불필요한 API 요청 줄이기
네트워크 요청이 많아지면 앱 성능이 떨어질 수밖에 없습니다.
특히, 같은 데이터를 여러 번 요청하는 경우가 많다면 불필요한 API 호출을 줄이는 방법이 필요합니다.
📌 해결 방법:
- 이전에 불러온 데이터를 다시 사용할 수 있도록 캐싱
- 불필요한 네트워크 요청을 방지하는 Debounce & Throttle 적용
1️⃣ 캐싱을 활용해서 같은 요청 반복 방지
캐싱이란 한 번 불러온 데이터를 저장해두고, 다시 요청하지 않고 저장된 데이터를 활용하는 방식입니다.
React Native에서는 React Query, SWR 같은 데이터 관리 라이브러리를 활용해서 쉽게 구현할 수 있습니다.
📌 React Query로 데이터 캐싱 적용 예제
import React from 'react';
import { View, Text, FlatList, ActivityIndicator } from 'react-native';
import { useQuery } from '@tanstack/react-query';
import axios from 'axios';
const fetchPosts = async () => {
const { data } = await axios.get('https://jsonplaceholder.typicode.com/posts');
return data;
};
const QueryExample = () => {
const { data, isLoading, error } = useQuery(['posts'], fetchPosts, {
staleTime: 1000 * 60 * 5, // 5분 동안 데이터 캐싱
});
if (isLoading) return <ActivityIndicator size="large" color="blue" />;
if (error) return <Text>데이터를 불러오는 데 실패했습니다.</Text>;
return (
<FlatList
data={data}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => <Text>{item.title}</Text>}
/>
);
};
export default QueryExample;
📌 코드 설명
- useQuery(['posts'], fetchPosts, { staleTime: 1000 * 60 * 5 })
- staleTime을 설정하면, 5분 동안 같은 API 요청을 반복하지 않음.
- 즉, 앱을 다시 실행하거나 화면을 새로고침해도 캐싱된 데이터를 우선 사용하고, 필요할 때만 API 요청을 보냄.
👉 이렇게 하면 같은 데이터를 불필요하게 여러 번 요청하지 않아서 성능이 훨씬 좋아짐.
2️⃣ Debounce & Throttle 적용하기 (검색 & 빠른 요청 방지)
📌 Debounce: 사용자가 입력을 멈춘 후 일정 시간이 지나면 요청을 보냄.
📌 Throttle: 일정 시간마다 한 번씩 요청을 보냄.
예를 들어, 검색창에 입력할 때마다 API 요청을 보내면 비효율적이기 때문에, Debounce를 적용하면 불필요한 요청을 줄일 수 있음.
📌 Debounce 적용 예제 (lodash 사용)
import React, { useState, useCallback } from 'react';
import { View, TextInput, FlatList, Text } from 'react-native';
import axios from 'axios';
import debounce from 'lodash.debounce';
const SearchComponent = () => {
const [query, setQuery] = useState('');
const [results, setResults] = useState([]);
const fetchSearchResults = async (text) => {
const response = await axios.get(`https://jsonplaceholder.typicode.com/posts?q=${text}`);
setResults(response.data);
};
const debouncedSearch = useCallback(debounce(fetchSearchResults, 500), []);
return (
<View>
<TextInput
placeholder="검색어 입력"
onChangeText={(text) => {
setQuery(text);
debouncedSearch(text);
}}
/>
<FlatList
data={results}
keyExtractor={(item) => item.id.toString()}
renderItem={({ item }) => <Text>{item.title}</Text>}
/>
</View>
);
};
export default SearchComponent;
📌 코드 설명
- debounce(fetchSearchResults, 500) → 사용자가 입력을 멈춘 후 500ms 뒤에 API 요청을 보냄.
- 입력할 때마다 API 요청을 보내지 않아서, 네트워크 부하를 줄이고 성능을 최적화할 수 있음.
👉 검색창, 버튼 클릭, 스크롤 이벤트 등에서도 Debounce & Throttle을 활용하면 성능 최적화에 유용함!
2. 로딩 처리 최적화 (Skeleton UI 활용)
네트워크 요청이 느려지면, 사용자가 아무 반응 없이 빈 화면을 보게 되는 문제가 발생할 수 있습니다.
이를 해결하려면 로딩 상태를 사용자에게 자연스럽게 보여줄 방법이 필요합니다.
📌 Skeleton UI란?
- API 요청이 끝날 때까지, 임시로 비슷한 모양의 UI를 먼저 보여주고, 데이터가 로드되면 실제 내용을 표시하는 방식
- 앱을 더 빠르게 느껴지게 만드는 효과가 있음.
📌 React Native에서 Skeleton UI 구현 예제
import React, { useState, useEffect } from 'react';
import { View, Text, ActivityIndicator, StyleSheet } from 'react-native';
const SkeletonExample = () => {
const [loading, setLoading] = useState(true);
const [data, setData] = useState(null);
useEffect(() => {
setTimeout(() => {
setData("API 데이터 로드 완료!");
setLoading(false);
}, 3000);
}, []);
return (
<View style={styles.container}>
{loading ? (
<View style={styles.skeletonBox} />
) : (
<Text>{data}</Text>
)}
</View>
);
};
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center' },
skeletonBox: { width: 200, height: 30, backgroundColor: '#ddd', borderRadius: 5 },
});
export default SkeletonExample;
👉 이렇게 하면, 데이터가 로드되기 전까지 빈 화면 대신 "로딩 중" UI를 보여줄 수 있음!
정리 및 다음 단계
✅ React Query를 활용한 API 캐싱 → 불필요한 요청 방지
✅ Debounce & Throttle 적용 → 빠른 요청 반복 방지
✅ Skeleton UI 적용 → 사용자 경험 향상
📌 출처 및 참고 자료
'React-Native(RN)' 카테고리의 다른 글
React Native에서 데이터 저장하는 방법 (로컬 vs. 클라우드) (0) | 2025.02.07 |
---|---|
React Native에서 API 요청하고 데이터 가져오기 (fetch & axios 활용법) (1) | 2025.02.06 |
React Native에서 상태 관리하기 (useState, useEffect 활용법) (0) | 2025.02.05 |
React Native에서 리스트뷰 구현하기 (FlatList, ScrollView) (0) | 2025.02.04 |
React Native에서 화면 전환 구현하기 🚀 (0) | 2025.02.03 |