
์ฑ์ ์ด๋ฏธ์ง๊ฐ ๋ง์์ง๋ฉด ์ฑ๋ฅ์ด ๋ ๋จ์ด์ง๊ณ ,
์ด๊ธฐ ๋ก๋ฉ ์๊ฐ๋ ๊ธธ์ด์ง๊ฒ ๋๋ค.
์ด๋ฅผ ํด๊ฒฐํ๋ ๋ํ์ ์ธ ๋ฐฉ๋ฒ์ด ๋ฐ๋ก Lazy Loading, ์ฆ ์ง์ฐ ๋ก๋ฉ์ด๋ค.
์ด๋ฒ ๊ธ์์๋ React Native์์ ์ด๋ฏธ์ง Lazy Loading์ ๊ตฌํํ ์ ์๋
๊ฐ์ฅ ์ค์ฉ์ ์ธ ๋ฐฉ์๋ค์ ์๊ฐํ๋ค.
Lazy Loading์ "ํ๋ฉด์ ๋ค์ด์ค๊ธฐ ์ ๊น์ง ์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฌ์ค์ง ์์"์ผ๋ก
์ฑ๋ฅ๊ณผ UX๋ฅผ ๋์์ ํฅ์์ํฌ ์ ์๋ ์ ๋ต์ด๋ค.
React Native์๋ ๋ธ๋ผ์ฐ์ ์ Intersection Observer๋ ์์ง๋ง,
FlatList์ onViewableItemsChanged๋ฅผ ์ฌ์ฉํ๋ฉด ์ ์ฌํ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋ค.
<FlatList
data={images}
renderItem={renderItem}
onViewableItemsChanged={onViewableItemsChanged}
viewabilityConfig={{ itemVisiblePercentThreshold: 50 }}
/>
const onViewableItemsChanged = useRef(({ viewableItems }) => {
const visibleIds = viewableItems.map((item) => item.item.id);
setVisibleImageIds(visibleIds);
}).current;
โ
ํ๋ฉด์ 50% ์ด์ ๋ณด์ด๋ ์์ดํ
๋ง ๊ฐ์งํด์
๋ ๋๋ง ์กฐ๊ฑด์ผ๋ก ์ฌ์ฉํ ์ ์๋ค.
function LazyImage({ uri, shouldLoad }) {
if (!shouldLoad) {
return <View style={{ width: 200, height: 200, backgroundColor: '#eee' }} />;
}
return (
<Image
source={{ uri }}
style={{ width: 200, height: 200 }}
resizeMode="cover"
/>
);
}
<FlatList
data={data}
renderItem={({ item }) => (
<LazyImage
uri={item.image}
shouldLoad={visibleImageIds.includes(item.id)}
/>
)}
onViewableItemsChanged={onViewableItemsChanged}
/>
<Image /> ๋ ๋๋ง | ํญ๋ชฉ | ์ ๋ต |
|---|---|
| ์บ์ฑ | react-native-fast-image ์ฌ์ฉ (์๋ ์บ์ฑ) |
| ์ด๋ฏธ์ง ์์ถ | ์๋ฒ์์ WebP, ์์ถ ๋ฒ์ ์ ๊ณต |
| ๋๋ฐ์ด์ฑ | onViewableItemsChanged์ debounce ์ ์ฉ ๊ฐ๋ฅ |
| ํด์๋ ๋์ | @2x, @3x ๊ตฌ์ฑ ํ์ |
FlatList์ 100์ฅ ๋๋ ์ด๋ฏธ์ง๊ฐ ์์ ๋
๋ ๋๋ง ์ง์ฐ์ด ์ฌํ๊ณ , ์คํฌ๋กค๋ ๋ง์ด ๋๊ฒผ๋ค.
๊ทธ๊ฑธ Lazy Loading์ผ๋ก ๋ฐ๊พธ๋๊น
ํ๋ฉด ์ง์
์์ ์๋ง ์ด๋ฏธ์ง๊ฐ ๋ก๋ฉ๋์ด
์คํฌ๋กค ์ฑ๋ฅ๊ณผ ๋ฉ๋ชจ๋ฆฌ ์ ์ ์จ์ด ํฌ๊ฒ ๊ฐ์ ๋๋ค.
์ง๊ธ์ ๋ฌด์กฐ๊ฑด LazyImage ๊ฐ์ ์ปดํฌ๋ํธ๋ฅผ ๋ง๋ค์ด
๊ณตํต ์ด๋ฏธ์ง ์ปดํฌ๋ํธ๋ก ํ์ฉํ๊ณ ์๋ค.
๐ข โ์ฑ๋ฅ์ ๋น ๋ฅธ ์ฝ๋๊ฐ ์๋๋ผ, ๋ถํ์ํ ์ฝ๋๋ฅผ ์ค์ด๋ ๋ฐ์ ๋์จ๋ค.โ