단계별 성능 최적화 계획
1. 메모리 누수 방지
1.1 메모리 누수가 발생하는 일반적인 원인
const BadExample = () => {
useEffect(() => {
const interval = setInterval(() => {
fetchData();
}, 1000);
// 메모리 누수 발생! cleanup 함수 없음
}, []);
};
1.2 메모리 누수 해결 방법
const GoodExample = () => {
useEffect(() => {
const interval = setInterval(() => {
fetchData();
}, 1000);
return () => {
clearInterval(interval);
// 구독 해제
someSubscription?.unsubscribe();
// 이벤트 리스너 제거
someEventEmitter?.remove();
};
}, []);
};
2. 렌더링 성능 최적화
2.1 불필요한 리렌더링 방지
const ItemComponent = React.memo(({ item }) => {
return (
<View>
<Text>{item.title}</Text>
<Text>{item.description}</Text>
</View>
);
});
const OptimizedList = ({ data }) => {
const renderItem = useCallback(({ item }) => (
<ItemComponent item={item} />
), []);
const memoizedData = useMemo(() =>
data.map(item => ({
...item,
processed: heavyComputation(item)
}))
, [data]);
return (
<FlatList
data={memoizedData}
renderItem={renderItem}
getItemLayout={(data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
})}
removeClippedSubviews={true}
maxToRenderPerBatch={10}
windowSize={5}
initialNumToRender={5}
/>
);
};
3. 이미지 최적화
3.1 이미지 캐싱 및 사이즈 최적화
import FastImage from 'react-native-fast-image';
const OptimizedImage = ({ uri, size }) => {
const [imageError, setImageError] = useState(false);
const [loading, setLoading] = useState(true);
const imageSize = useMemo(() => ({
width: size,
height: size,
}), [size]);
const source = useMemo(() => ({
uri: uri,
headers: { Authorization: 'auth-token' },
priority: FastImage.priority.normal,
cache: FastImage.cacheControl.immutable,
}), [uri]);
return (
<View style={[styles.container, imageSize]}>
<FastImage
style={imageSize}
source={source}
onLoadStart={() => setLoading(true)}
onLoadEnd={() => setLoading(false)}
onError={() => setImageError(true)}
resizeMode={FastImage.resizeMode.cover}
/>
{loading && <ActivityIndicator />}
{imageError && <Text>이미지 로드 실패</Text>}
</View>
);
};
3.2 이미지 프리로딩
const preloadImages = (images) => {
const imageUrls = images.map(image => ({
uri: image.uri,
priority: FastImage.priority.low,
}));
FastImage.preload(imageUrls);
};
4. 성능 모니터링
4.1 성능 측정 유틸리티
import { PerformanceObserver, performance } from 'perf_hooks';
export const PerformanceMonitor = {
startMeasure: (label) => {
performance.mark(`${label}-start`);
},
endMeasure: (label) => {
performance.mark(`${label}-end`);
performance.measure(
label,
`${label}-start`,
`${label}-end`
);
const measurements = performance.getEntriesByName(label);
console.log(`${label} 실행 시간:`, measurements[0].duration);
},
setupObserver: () => {
const obs = new PerformanceObserver((list) => {
const entries = list.getEntries();
entries.forEach((entry) => {
console.log(`${entry.name}: ${entry.duration}ms`);
});
});
obs.observe({ entryTypes: ['measure'] });
return obs;
}
};
4.2 실제 사용 예시
const MainScreen = () => {
useEffect(() => {
const observer = PerformanceMonitor.setupObserver();
return () => {
observer.disconnect();
};
}, []);
const handlePress = () => {
PerformanceMonitor.startMeasure('expensive-operation');
// 무거운 작업 수행
expensiveOperation();
PerformanceMonitor.endMeasure('expensive-operation');
};
return (
<View>
<Button onPress={handlePress} title="성능 측정" />
</View>
);
};
결론
react-native는 최적화가 되어있지 않으면 성능저하가 두드러지게 나타나기 때문에 반드시 코드를 작성한 뒤에 성능측정 하여 최적화를 해주어야할 것 같다.
'react-native' 카테고리의 다른 글
react-native Ios gesture-handler 빌드 오류 (1) | 2025.02.24 |
---|---|
React-native FlatList 에서 getItemLayout 이란? (0) | 2025.02.23 |
React Native에서 FlatList 성능 최적화: 5가지 실용적인 방법 (0) | 2025.02.23 |
[react-native] Task :app:mergeDebugNativeLibs FAILED 에러,오류 해결 (3) | 2021.04.01 |