Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FE] refactor: MSW 환경에서 무한 스크롤 API 응답을 서버와 통일하고, 빈 리뷰에 대한 옵저버 로직 개선 #754

Merged
merged 5 commits into from
Oct 2, 2024

Conversation

soosoo22
Copy link
Contributor

@soosoo22 soosoo22 commented Sep 28, 2024


🚀 어떤 기능을 구현했나요 ?

  • 기존에는 MSW 환경에서의 API 응답 방식이 서버에서 보내주는 응답 방식과 달라서 MSW환경에서는 제대로 무한 스크롤 기능이 작동하는데, 서버와 직접적으로 연동하면 작동하지 않는 문제가 있었습니다. 이 문제를 해결하기 위해, 서버와 MSW 간의 응답 방식을 통일하고, 무한 스크롤 시 더 이상 받은 리뷰가 없을 때 hasNextPage를 false로 반환하도록 수정했습니다.

🔥 어떻게 해결했나요 ?

기존에는 msw 핸들러에서 마지막 페이지가 아니고 lastReviewId가 null이 아닐 때, lastReviewId에 size를 더해주고 그러지 않을 경우 null을 반환하는 방식이었습니다. 그러나 서버에서는 lastReviewId에 null을 넣지 않으므로, 수정된 로직에서는 리뷰가 빈 배열이 아닐 경우, lastReviewId에 마지막 리뷰 id를 넣고, 그렇지 않으면 0을 넣도록 수정했습니다.

// mocks/handlers/review.ts
// 수정 전
lastReviewId: !isLastPage && lastReviewId !== null ? lastReviewId + size : null

// 수정 후
lastReviewId: paginatedReviews.length > 0 ? paginatedReviews[paginatedReviews.length - 1].reviewId : 0

참고로 서버에서는 무한 스크롤 시, 리뷰가 더이상 없을 경우, lastReviewId에 0을 넣어서 보내줍니다.
스크린샷 2024-09-28 오후 3 00 42

useInfiniteScroll의 IntersectionObserver 로직에서 isLastPage를 사용하여 옵저버를 해제하는 방식이 아닌 useGetReviewList 훅에서 hasNextPage를 계산해서 보내주는 방식으로 변경했습니다. 받은 리뷰가 더이상 없을 경우 즉, 빈 배열일 경우 hasNextPage를 false로 설정해서 useInfiniteScroll에서 fetchNextPage가 실행되지 않도록 수정했습니다.

const useGetReviewList = () => {
  // ...

  const hasNextPage = !result.data.pages.some((page) => page.reviews.length === 0);

  return { ...result, hasNextPage };
};
const useInfiniteScroll = ({ fetchNextPage, hasNextPage, isLoading }: InfiniteScrollProps) => {
  const observer = useRef<IntersectionObserver | null>(null);

  const lastElementRef = useCallback(
    // ...

      observer.current = new IntersectionObserver((entries) => {
        if (entries[0].isIntersecting && hasNextPage) { // hasNextPage 추가
          fetchNextPage();
        }
      });

      if (node) observer.current.observe(node);
    },
    [isLoading, fetchNextPage, hasNextPage],
  );

  return lastElementRef;
};

⭐️ 방식 변경 => isLastPage를 활용한 무한 스크롤 구현 ⭐️

위 방식인 hasNextPage를 계산해서 보내주는 방식이 아닌 서버에서 보내주는 isLastPage를 활용하는 방식으로 변경했습니다.

서버에서 보내주는 isLastPage 값을 활용해서 옵저버를 해제하는 방식으로 수정했습니다. 기존에 문제가 발생했던 이유는, 첫 번째 페이지의 isLastPage 값을 사용하면서 항상 false를 넘겨주고 있었기 때문에 옵저버가 해제되지 않고 계속해서 페이지를 요청하게 되는 상황이 발생했습니다. 이를 마지막으로 받은 페이지의 isLastPage 값을 기반으로 하여 옵저버를 해제하도록 해서 문제를 해결했습니다.

  const isLastPage = data.pages[data.pages.length - 1].isLastPage;

📝 어떤 부분에 집중해서 리뷰해야 할까요?

  • msw 환경에서 살짝 과장 보태서 백만번 확인해봤습니다..... 그래도 한번씩 확인 부탁드립니다....

📚 참고 자료, 할 말

무한스크롤_최최최최최최최종

@@ -19,7 +19,9 @@ const useGetReviewList = () => {
staleTime: 1 * 60 * 1000,
});

return result;
const hasNextPage = !result.data.pages.some((page) => page.reviews.length === 0);
Copy link
Contributor

@BadaHertz52 BadaHertz52 Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

서버에서 내려주는 isLastPage를 사용하지 않은 이유가 있나요?
리뷰 데이터가 많아질 수록 배열 시간 복잡도가 올라가서 isLastPage를 사용하지 않고 배열을 순회해야하는 것에 의문이 들어서요

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

서버에서 isLastPage를 true 주고 다시 한번 api 요청을 해서, 불필요한 api 요청이 추가로 가는 것이 아닌가 싶네요

Copy link
Contributor Author

@soosoo22 soosoo22 Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

서버에서 내려주는 isLastPage를 사용하지 않은 이유가 있나요? 리뷰 데이터가 많아질 수록 배열 시간 복잡도가 올라가서 isLastPage를 사용하지 않고 배열을 순회해야하는 가라는 것에 의문이 들어서요

isLastPage를 사용해서 옵저버를 해제하면 무한스크롤로 받은 리뷰를 다 확인했을 때 살짝 올라갔다가 내려가면 다시 첫 리뷰를 불러오면서 리뷰가 무한 증식이 되어버립니다... 제가 보기엔 isLastReviewId가 0이면 첫 리뷰를 불러오고 있는데 거기서 문제가 있는게 아닌가... 싶네요..

⭐️해결 완료⭐️

콘솔로 isLastPage를 찍어서 확인해보니 false만을 넘겨주고 있더라고요. isLastPage가 false로만 넘어가던 이유는, 데이터를 받는 과정에서 가장 첫 번째 페이지의 isLastPage 값을 사용하고 있었어요. 실제로는 마지막으로 받은 페이지의 isLastPage 값을 넘겨줘야 했던 상황이었는데 말이죠...

수정한 방식인 data.pages[data.pages.length - 1].isLastPage;를 넘겨주는 방식으로 수정했습니다. 마지막 페이지의 데이터를 기준으로 isLastPage 값을 설정해주어서, 올바르게 동작하네요!

Copy link
Contributor Author

@soosoo22 soosoo22 Oct 2, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

서버에서 isLastPage를 true 주고 다시 한번 api 요청을 해서, 불필요한 api 요청이 추가로 가는 것이 아닌가 싶네요

맞습니다... 이 부분은 수정해야 겠네요.

⭐️ 해결 완료 ⭐️

isLastPage를 활용해서 true를 받으면 바로 옵저버에 fetchNextPage 함수가 호출되지 않게 수정했습니다. => 추가 api 요청이 가지 않습니다.

Copy link
Contributor

@BadaHertz52 BadaHertz52 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

쑤쑤 무한 증식 오류 수정한 거 확인했어요. 고생했어요 (부디 서버에서도 문제가 없기를)

isLastPage를 사용하지 않는 부분 그로 인해 불필요한 api 요청이 한 번 더 생기는 일이 있어요
해당 코멘트 확인해주세요

Copy link
Contributor

@chysis chysis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 동일하게 마지막 리뷰까지 확인하고 나서 API 요청이 한 번 더 되는 것을 확인했어요!
확인했다는 의미로 코멘트 먼저 남겨둡니다 :)

Copy link
Contributor

@ImxYJL ImxYJL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 isLastPage를 사용하지 않는 이유가 궁금해서 일단 코멘트만 남겨둡니당

Copy link
Contributor

@ImxYJL ImxYJL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

쑤쑤 고생했어요!~!!

Copy link
Contributor

@BadaHertz52 BadaHertz52 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

역시 무스 장인 쑤쑤!!!! 해냈네요 무스 해결한 거 축하해요!!!!

ClappingPikachuGIF

Copy link
Contributor

@chysis chysis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

무한 증식 이슈 해결되었고, 마지막 아이템까지 갔을 때 요청 더 안 가는 것 확인했어요 :)
무한 스크롤 고생 많았어요~~~

@chysis chysis merged commit ab4f5c2 into develop Oct 2, 2024
4 checks passed
@donghoony donghoony deleted the fe/rafctor/752-infinity-scroll-stop branch October 10, 2024 01:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

[FE] 무한 스크롤 시, 서버와 MSW의 API 응답 방식을 통일한다.
4 participants