@@ -14,31 +14,35 @@ const OOTD: React.FC = () => {
1414 const [ modalContent , setModalContent ] = useState ( '알 수 없는 오류입니다.\n관리자에게 문의해 주세요.' ) ;
1515 const [ isStatusModalOpen , setIsStatusModalOpen ] = useState ( false ) ;
1616
17- const [ reachedEnd , setReachedEnd ] = useState ( false ) ;
18- const [ isFetching , setIsFetching ] = useState ( false ) ;
17+ // API 요청 중인지 확인하는 변수 (렌더링 없이 상태 관리)
18+ const isFetchingRef = useRef ( false ) ;
19+ // 모든 데이터를 불러왔는지 확인하는 변수
20+ const isReachedEndRef = useRef ( false ) ;
1921
20- const feedPageRef = useRef ( 1 ) ; // 현재 페이지 번호를 참조하는 변수, 리렌더링 없이 값만 업데이트 하기 위해 상태가 아닌 useRef 사용
22+ // 현재 페이지 번호를 참조하는 변수, 리렌더링 없이 값만 업데이트하기 위해 상태가 아닌 useRef 사용
23+ const feedPageRef = useRef ( 1 ) ;
2124
2225 // 세션 스토리지에서 이전 스크롤 위치를 가져와 초기화
2326 const savedScrollPosition = sessionStorage . getItem ( 'scrollPosition' ) ;
2427 const scrollPositionRef = useRef ( Number ( savedScrollPosition ) || 0 ) ;
2528
26- const observerRef = useRef < IntersectionObserver | null > ( null ) ; // IntersectionObserver 인스턴스를 참조하는 변수
27- const loadMoreRef = useRef < HTMLDivElement | null > ( null ) ; // 더 많은 데이터를 로드할 때 관찰할 마지막 요소의 DOM을 참조
29+ // IntersectionObserver 인스턴스를 참조하는 변수
30+ const observerRef = useRef < IntersectionObserver | null > ( null ) ;
31+ // 더 많은 데이터를 로드할 때 관찰할 마지막 요소의 DOM을 참조
32+ const loadMoreRef = useRef < HTMLDivElement | null > ( null ) ;
2833
2934 // 전체 게시글(피드) 조회 API
3035 const getPostList = async ( ) => {
31- if ( reachedEnd || isFetching ) return ;
32- // 사용자가 스크롤을 빠르게 내리거나 ntersection Observer가 여러 번 트리거될 경우, 중복된 API 요청 발생 가능.
33- // 이를 막기 위해 isFetching 상태를 확인하고, 현재 요청 중인 상태라면 추가 요청을 막음
36+ // 모든 데이터를 불러왔거나 요청 중이라면 함수 실행 중단
37+ if ( isReachedEndRef . current || isFetchingRef . current ) return ;
3438
35- setIsFetching ( true ) ;
39+ isFetchingRef . current = true ; // 요청 중임을 표시
3640 try {
3741 const response = await getPostListApi ( feedPageRef . current , 20 ) ;
3842
3943 if ( response . isSuccess ) {
4044 if ( response . data . post . length === 0 ) {
41- setReachedEnd ( true ) ;
45+ isReachedEndRef . current = true ; // 더 이상 불러올 데이터가 없음을 표시
4246 } else {
4347 setFeeds ( ( prevFeeds ) => [ ...prevFeeds , ...response . data . post ] ) ;
4448 feedPageRef . current += 1 ;
@@ -49,28 +53,29 @@ const OOTD: React.FC = () => {
4953 setModalContent ( errorMessage ) ;
5054 setIsStatusModalOpen ( true ) ;
5155 } finally {
52- setIsFetching ( false ) ;
56+ isFetchingRef . current = false ;
5357 }
5458 } ;
5559
5660 useEffect ( ( ) => {
57- if ( reachedEnd && observerRef . current && loadMoreRef . current ) {
58- observerRef . current . unobserve ( loadMoreRef . current ) ;
59- return ; // 데이터의 끝에 다다르면 옵저버 해제. (더이상 피드가 없으면)
61+ if ( isReachedEndRef . current && observerRef . current && loadMoreRef . current ) {
62+ observerRef . current . unobserve ( loadMoreRef . current ) ; // 데이터의 끝에 다다르면 옵저버 해제 (더이상 피드가 없으면)
63+ return ;
6064 }
6165
62- observerRef . current = new IntersectionObserver ( // Intersection Observer 생성
66+ // Intersection Observer 생성
67+ observerRef . current = new IntersectionObserver (
6368 debounce ( ( entries ) => {
6469 const target = entries [ 0 ] ;
6570 console . log ( 'Intersection Observer:' , target . isIntersecting ) ;
66- if ( target . isIntersecting && ! isFetching && ! reachedEnd ) {
67- // 요소가 화면에 보이고 있고, 요청 중이 아니며며 끝에 도달하지 않았다면 api 호출
71+ if ( target . isIntersecting && ! isFetchingRef . current && ! isReachedEndRef . current ) {
72+ // 요소가 화면에 보이고 있고, 요청 중이 아니며 끝에 도달하지 않았다면 API 호출
6873 getPostList ( ) ;
6974 }
70- } , 300 ) , // 디바운스 적용해 스크롤 이벤트 제어. 스크롤마다 이벤트 호출하는 것이 아닌 마지막 스크롤 이후 300ms동안 동작이 없으면 이벤트 호출
75+ } , 300 ) , // 디바운스 적용, 마지막 스크롤 이후 300ms 동안 동작이 없으면 이벤트 호출
7176 {
7277 root : null ,
73- rootMargin : '100px' , // // 요소가 보이기 100px 전에 미리 데이터 로드
78+ rootMargin : '100px' , // 요소가 보이기 100px 전에 미리 데이터 로드
7479 threshold : 0 , // 요소가 아주 조금이라도 보이면 트리거
7580 } ,
7681 ) ;
@@ -80,12 +85,12 @@ const OOTD: React.FC = () => {
8085 observerRef . current . observe ( loadMoreRef . current ) ;
8186 }
8287 return ( ) => {
83- // 컴포넌트가 언마운트되거나 의존성이 변경될 때 옵저버 해제
88+ // 컴포넌트 언마운트 시 옵저버 해제
8489 if ( observerRef . current && loadMoreRef . current ) {
8590 observerRef . current . unobserve ( loadMoreRef . current ) ;
8691 }
8792 } ;
88- } , [ isFetching , reachedEnd ] ) ;
93+ } , [ ] ) ;
8994
9095 useEffect ( ( ) => {
9196 // 첫 로드 시 API 호출
0 commit comments