๐ Lazy Loading์ ๊ตฌํํด๋ณธ ๋ฐฉ๋ฒ
Vue ๊ธฐ๋ฐ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์, Lazy Loading์ ์ ์ฉํด๋ณผ ๊ธฐํ๊ฐ ์์๋ค.
๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ ์ฉํด๋ดค๋๋ฐ,
1. ๋ฐฑ์๋์ ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ์์ฒญํด์, ํ๋ก ํธ ๋จ์์ Chunk๋ก ์๋ผ์ ๋ณด์ฌ์ฃผ๊ธฐ
2. ๋ฐฑ์๋์ ๋ถ๋ถ์ ์ผ๋ก ๋ค์ ๋ฐ์ดํฐ๋ฅผ ์์ฒญํด์์ ๋ณด์ฌ์ฃผ๊ธฐ
๋ฐ์ดํฐ๊ฐ 1000~2000๊ฐ ์ ๋์์ ๋๋ 1๋ฒ๋ ๋ฌด๋ฆฌ ์์ด ๋์ ํ์๋ค.
๊ทธ๋ฐ๋ฐ 4000~5000๊ฐ ์ด์ ๋์ด๊ฐ๊ธฐ ์์ํ๋๊น,
๋ฐฑ์๋์์ ์ ๋ณด๋ฅผ ๋ถ๋ฌ์ค๋๋ฐ๋ ์ค๋๊ฑธ๋ฆฌ๊ณ (ํนํ ๋คํธ์ํฌ๊ฐ ๋๋ฆฐ ๊ณณ์์๋ ๋๋์ฑ),
ํ๋ก ํธ ๋จ์์ ํ์ฒ๋ฆฌํ๋๋ฐ๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ง์ด ์ก์๋จน๊ธฐ ์์ํ๋ค.
๊ทธ๋์ ๋๋ฒ์งธ ๋ฐฉ๋ฒ์ ์ ์ฉํ๊ธฐ๋ก ๊ฒฐ์ !
๋๋ฒ์งธ ๋ฐฉ๋ฒ์๋ ๊ตฌํ ๋ฐฉ๋ฒ์ด ์ฌ๋ฌ๊ฐ์ง๊ฐ ์๋๋ฐ,
์ฒ์์๋ 'Scroll ์ด๋ฒคํธ'๋ฅผ ๋ฐ์์์ผ์ ์ ์ฒด ์ฐฝ ์ฌ์ด์ฆ์ ํ์ฌ ์์น๋ฅผ ๋น๊ตํด์ผํ๋ ๊ณ ๋ฏผํ์๋ค.
๋ฌผ๋ก , ์ด ๋ฐฉ๋ฒ์ด ๋ถ๊ฐ๋ฅํ๊ฑด ์๋์ง๋ง, scroll ์ด๋ฒคํธ๊ฐ ๋ฌด์ํ ๋ง์ด ๋ฐ์ํ๋ค๋ ์ ์ ๋ถํ๊ฐ ๊ฑธ๋ฆด ๊ฒ์ ๋ถ๋ช ํ๋ค.
scroll ์ด๋ฒคํธ์ `debounce` ๋ `throttle`์ ์ ์ฉํ๋ ๋ฐฉ๋ฒ๋ ์๊ฐํด๋ดค์ง๋ง,
Intersection Observer๋ผ๋ API๊ฐ ์๋ค๋ ๊ฒ์ ์๊ฒ๋๊ณ ,
์ด API๋ฅผ ์ ์ฉํ๋ฉด `debounce`, `throttle` ์์ด๋ ์ฑ๋ฅ์ ๋ฌด๋ฆฌ๊ฐ ์๋ค๋ ๊ฒ์ ์๊ฒ๋์ด ๋ด๊ฒ ๊ต์ฅํ ํ์ ์ด์๋ค.
โจ Debounce
์ด๋ฒคํธ๊ฐ ์ค๋ณต์ผ๋ก ๋ฐ์ํ ๊ฒฝ์ฐ, ์ต์ด ํน์ ๋ง์ง๋ง ์ด๋ฒคํธ๋ง ์คํํ๋๋ก ์ ์ดํ๋ ์ค์
โจ Throttle
์ด๋ฒคํธ๋ฅผ ์ผ์ ์๊ฐ๋์ ํ๋ฒ๋ง ์คํ๋๋๋ก ์ ์ดํ๋ ์ค์
๐ Intersection Observer API
- Intersection Observer API : ๊ต์ฐจ ๊ด์ฐฐ์ API
- ๋ด๊ฐ ๊ด์ฐฐ์๋ก ์ง์ ํด๋์ ์์๊ฐ ์ฌ์ฉ์์ ํ๋ฉด์ ๋ ธ์ถ๋์๋์ง๋ฅผ ์๋ ค์ฃผ๋ API
๐ ์ฌ์ฉ ๋ฐฉ๋ฒ
1. Observer.vue ์์ฑ
<template>
<div ref="trigger"></div>
</template>
<script setup>
import { onBeforeUnmount, onMounted, ref } from 'vue';
let observer = null;
let observerOptions = {
root: null,
rootMargin: '0px', // ํธ๋ฆฌ๊ฑฐ Margin ์์ญ
threshold: 0.1, // ํธ๋ฆฌ๊ฑฐ๊ฐ ํ๋ฉด์ ์ผ๋ง๋ ๋ณด์์ ๋ ๊ฐ์งํ ๊ฒ์ธ์ง (0.1 = 10%)
};
const emits = defineEmits(['show', 'hidden']);
onMounted(() => {
createObserver(); // Observer ๋ฑ๋กํ๋ ํจ์๋ก ์ฐ๊ฒฐ
});
onBeforeUnmount(() => {
observer.disconnect(); // Observer ์ฐ๊ฒฐ ํด์
});
const trigger = ref();
const createObserver = () => {
observer = new IntersectionObserver(entries => { // ๋ถ๋ชจ๋ก emits
if (entries[0].isIntersecting) {
emits('show');
} else {
emits('hidden');
}
}, observerOptions);
observer.observe(trigger.value);
};
</script>
2. ์ฌ์ฉํ๊ณ ์ถ์ ๊ณณ์์ ์ฌ์ฉ
<template>
<div>
<div class="lazy-loading-container">
<div class="lazy-loading-data" v-for="(imageSrc, index) in rData.imageList" :key="index">
<img :src="imageSrc" alt="" />
</div>
<Observer @show="loadMore" />
</div>
</div>
</template>
<script setup>
import Observer from "@/components/Observer.vue";
import {reactive} from "vue";
const rData = reactive({imageList: [], page: 1});
const loadMore = async () => {
const fetchData = await getAllImageList(rData.page + 1);
if (fetchData) {
rData.imageList = [...rData.imageList, ...fetchData];
rData.page += 1;
}
};
</script>
โ ์ฐธ๊ณ ํ ์ฌ์ดํธ
https://velog.io/@godud2604/์ด๋ฏธ์ง-์ต์ ํ-Lazy-Load-Intersection-Observer-API
https://samsara1019.tistory.com/77
https://velog.io/@jejualrock/๋ฌดํ์คํฌ๋กค-ํด๋ผ์ด์ธํธ