티스토리 뷰
React 로 무한스크롤 구현하기! Intersection Observer API 를 사용하는 방법?
Intersetction Observer API란?
Intersection Observer API는 뷰포트 내 요소의 교차(intersection) 상태를 관찰하는 API입니다. 뷰포트는 웹 페이지에서 보이는 영역을 말하며, Intersection Observer API를 사용하면 이 영역 내에서 요소들이 어떤 상태인지를 비동기적으로 관찰할 수 있습니다.
Intersection Observer API는 크로스 브라우징을 지원하며, 모바일 기기에서도 정상적으로 작동합니다. 이 API를 이용하여 웹 페이지에서 무한 스크롤, 광고 배너 로딩, 이미지 지연 로딩 등 다양한 용도로 활용할 수 있습니다.
Intersection Observer API는 다음과 같은 메서드와 프로퍼티를 제공합니다.
- IntersectionObserver 생성자: IntersectionObserver 객체를 생성합니다.
- IntersectionObserver.observe(targetElement): 지정한 요소를 IntersectionObserver에 등록하여 교차 상태를 관찰합니다.
- IntersectionObserver.disconnect(): IntersectionObserver에서 등록한 모든 요소의 교차 관찰을 중지합니다.
- IntersectionObserver.unobserve(targetElement): 지정한 요소의 교차 관찰을 중지합니다.
- IntersectionObserverEntry.intersectionRatio: 교차 영역의 비율을 반환합니다.
- IntersectionObserverEntry.isIntersecting: 요소와 뷰포트가 교차하는지 여부를 반환합니다.
IntersectionObserver 생성자는 다음과 같은 옵션을 제공합니다.
- root: 교차를 관찰할 요소의 부모 요소를 지정합니다. 기본값은 브라우저의 뷰포트입니다.
- rootMargin: 교차 영역을 계산할 때, 지정한 마진 값을 고려합니다.
- threshold: 교차 영역의 비율이 지정한 값 이상일 때, 콜백 함수를 호출합니다. 기본값은 0입니다.
무한스크롤 구현 코드
초기값 선언과 함수 부분
// initial state
const [comments, setComments] = useState([]);
const [totalPage, setTotalPage] = useState(0);
const [isLoading, setIsLoading] = useState(false);
const [commentPage, setCommentPage] = useState(0); // 스크롤이 닿았을 때 새롭게 데이터 페이지를 바꿀 state
const pageEnd = useRef(); // 페이지의 마지막 요소(infinite scroll의 탐색 타겟)
const loadMore = () => {
if (commentPage < totalPage) {
setCommentPage((commentPage) => commentPage + 1);
}
if (commentPage === totalPage - 1) {
setIsLoading(false);
}
};
useEffect(() => {
if (isLoading) {
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting) {
loadMore();
}
},
{ threshold: 1 },
);
// 옵져버 탐색 시작
observer.observe(pageEnd.current);
}
}, [isLoading]);
return문
<div>
(생략)
{comments?.map((i) => {
return (
<div key={i.id}>
<Comment
commentId={i.id}
comment={i.comment}
nickname={i.nickname}
createdAt={i.createdAt}
comments={comments}
setComments={setComments}
/>
</div>
);
})}
<Target ref={pageEnd} />
</div>
깃허브
https://github.com/namoldak/Frontend/blob/main/src/components/Community/Post/PostDetail.jsx
React 에서 Intersection Observer API를 사용하지 않고 무한스크롤을 구현하는 방법은?
1. 스크롤 이벤트와 DOM 높이 비교
무한 스크롤을 구현하는 가장 간단한 방법 중 하나는 스크롤 이벤트를 사용하여 DOM의 높이와 스크롤 위치를 비교하는 것입니다.
import React, { useState, useEffect } from 'react';
function InfiniteScroll() {
const [data, setData] = useState([]);
const [page, setPage] = useState(1);
useEffect(() => {
// 초기 데이터 로드
fetchData();
}, []);
useEffect(() => {
// 스크롤 이벤트 리스너 등록
window.addEventListener('scroll', handleScroll);
return () => window.removeEventListener('scroll', handleScroll);
}, []);
const handleScroll = () => {
// 스크롤이 바닥에 닿았을 때 다음 페이지 데이터 로드
if (window.innerHeight + document.documentElement.scrollTop === document.documentElement.offsetHeight) {
fetchData();
}
};
const fetchData = async () => {
// API에서 데이터를 가져와서 data state에 추가
const response = await fetch(`https://example.com/api?page=${page}`);
const newData = await response.json();
setData((prevData) => [...prevData, ...newData]);
setPage((prevPage) => prevPage + 1);
};
return (
<ul>
{data.map((item) => (
<li key={item.id}>{item.title}</li>
))}
</ul>
);
}
export default InfiniteScroll;
위 코드에서 handleScroll 함수는 스크롤 이벤트가 발생할 때마다 호출됩니다. 이 함수는 현재 스크롤 위치와 DOM 높이를 비교하여 스크롤이 바닥에 닿았는지 확인합니다. 스크롤이 바닥에 닿으면 fetchData 함수를 호출하여 다음 페이지 데이터를 가져와서 data state에 추가합니다.
2. button 클릭으로 추가 데이터 가져오기
또 다른 방법은 무한 스크롤 대신 "더 보기" 버튼을 클릭하여 추가 데이터를 가져오는 것입니다.
import React, { useState, useEffect } from 'react';
function InfiniteScroll() {
const [data, setData] = useState([]);
const [page, setPage] = useState(1);
useEffect(() => {
// 초기 데이터 로드
fetchData();
}, []);
const handleLoadMore = () => {
// "더 보기" 버튼 클릭 시 다음 페이지 데이터 로드
fetchData();
setPage((prevPage) => prevPage + 1);
};
const fetchData = async () => {
// API에서 데이터를 가져와서 data state에 추가
const response = await fetch(`https://example.com/api?page=${page}`);
const newData = await response.json();
setData((prev
React 를 쓰지 않고 무한스크롤을 구현하는 방법은?
React를 사용하지 않고 무한 스크롤을 구현하는 방법에는 일반적으로 두 가지 방법이 있습니다.
- 스크롤 이벤트와 DOM 높이 비교
- 스크롤 이벤트를 사용하여 DOM의 높이와 스크롤 위치를 비교하는 방법입니다.
- 스크롤 위치와 DOM 높이를 비교하여 스크롤이 바닥에 닿았는지 확인하고, 바닥에 닿았다면 다음 페이지 데이터를 가져와서 페이지에 추가합니다.
- AJAX 요청과 데이터 렌더링
- AJAX 요청을 사용하여 페이지당 일정한 개수의 데이터를 가져오는 방법입니다.
- 초기 페이지 로드 시 일정한 개수의 데이터를 가져오고, 스크롤이 아래쪽에 가까워질 때마다 추가 데이터를 가져와서 페이지에 추가합니다.
두 방법 모두 JavaScript와 HTML을 사용하여 구현할 수 있습니다. 예를 들어, 첫 번째 방법의 경우 다음과 같은 코드를 사용할 수 있습니다.
// 스크롤 이벤트 리스너 등록
window.addEventListener('scroll', handleScroll);
// 스크롤 이벤트 핸들러
function handleScroll() {
// 스크롤이 바닥에 닿았는지 확인
if (window.innerHeight + window.scrollY === document.body.offsetHeight) {
// 다음 페이지 데이터 가져오기
const data = getNextPageData();
// 가져온 데이터를 페이지에 추가하기
renderData(data);
}
}
위 코드에서 window.addEventListener 함수를 사용하여 스크롤 이벤트 리스너를 등록하고, handleScroll 함수에서 스크롤이 바닥에 닿았는지 확인합니다. 바닥에 닿았을 때 getNextPageData 함수를 호출하여 다음 페이지 데이터를 가져오고, renderData 함수를 호출하여 가져온 데이터를 페이지에 추가합니다. 이때 renderData 함수는 가져온 데이터를 HTML 요소로 변환하여 페이지에 추가하는 역할을 합니다
'Projects' 카테고리의 다른 글
[Namoldak] WebRTC p2p 미디어 (카메라, 보이스) 연결 (0) | 2023.02.24 |
---|---|
[Namoldak] SockJs, STOMP 를 이용한 실시간 채팅 구현 (0) | 2023.02.24 |
[Namoldak] TroubleShooting_RefreshToken (0) | 2023.02.13 |
[Namoldak] EsLint & Prettier 설정 (0) | 2023.01.01 |
[Modu-house] 미니 프로젝트 트러블 슈팅 (1) | 2022.12.19 |