• 티스토리 홈
  • 프로필사진
    홍유진
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
홍유진
  • 프로필사진
    홍유진
    • 분류 전체보기 (22)
      • Coding Test (0)
      • Web Frontend (19)
        • Problem Solving (0)
        • HTML_CSS (10)
      • Workflow (1)
      • Database (1)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • Promise.all을 활용한 페이지네이션 해결
        2024년 06월 22일
        • 홍유진
        • 작성자
        • 2024.06.22.:37

        문제

        해결 전

        웹툰 목록 조회 기능을 구현하는데 총 웹툰 개수(total)이 2942개는 되지만 한 번에 30개씩만 받아와지면서 데이터를 전부를 불러오지 못하는 일이 발생했다.

         

        원인

        이 문제의 원인은 페이지네이션때문이였다. Swagger를 보니 query parameter로 page(페이지 번호), perPage(페이지당 항목 수)를 받을 수 있게 해주었는데 아마 API가 한 번에 많은 데이터를 제공하면 성능에 부담을 주기 때문에 데이터를 페이지로 나누어서 제공해준 거 같았다.

        useEffect(() => {
          const fetchFilteredWebtoons = async () => {
            setLoading(true);
            try {
              const apiURL = `${process.env.REACT_APP_API}/webtoons?provider=NAVER`;
              const response = await fetch(apiURL, {
                method: "GET",
                headers: {
                  "Content-Type": "application/json",
                },
              });
              if (!response.ok) {
                throw new Error("Network response was not ok");
              }
              const data = await response.json();
              console.log(data);
              setFilteredWebtoons(data.webtoons || []);
            } catch (error) {
              console.error("There was a problem with the fetch operation:", error);
            } finally {
              setLoading(false);
            }
          };
        
          fetchFilteredWebtoons();
        }, []);

        기존의 코드는 한 번의 요청으로 일부 데이터만 받아오기 때문에 모든 웹툰 데이터를 한 번에 가져올 수 없었다.

         

        해결 방법

        모든 데이터를 불러와야 하기때문에 병렬적으로 api를 호출할 수 있는 promise all을 통해 해결할 수 있었다. 위의 방법은 페이지별로 데이터를 요청한 후, 그 데이터를 합쳐서 사용하는 방법이다.

        1. 첫 번째 요청으로 전체 개수 파악
          • 첫 번째 요청을 보내서 총 웹툰 개수를 알아낸다. 이 정보는 모든 데이터를 가져오기 위해 필요하다. totalWebtoons 변수에 총 웹툰 개수를 저장하고, 이를 바탕으로 전체 페이지 수(totalPages)를 계산한다.
        2. 모든 페이지의 요청을 생성
          • for 루프를 사용하여 각 페이지에 대한 요청을 생성하고, 이 요청을 requests 배열에 저장한다. 페이지별로 요청을 만들어서 모든 데이터를 가져오게 한다.
        3. 모든 요청을 병렬로 실행
          • Promise.all을 사용하여 모든 페이지에 대한 요청을 병렬로 실행하고, 결과를 results 배열에 저장한다. 각 페이지의 결과에서 웹툰 목록을 추출하여 allWebtoons 배열에 합친다.
        4. 상태 업데이트:
          • 최종적으로 합쳐진 웹툰 데이터를 setFilteredWebtoons를 통해 상태로 설정한다.
        5. 첫 번째 요청을 보내서 총 웹툰 개수를 알아낸다. totalWebtoons 변수에 총 웹툰 개수를 저장하고, 이를 바탕으로 전체 페이지 수(totalPages)를 계산한다.
        useEffect(() => {
          const fetchAllWebtoons = async () => {
            setLoading(true);
            try {
              // API 기본 URL 설정
              const apiURL = `${process.env.REACT_APP_API}/webtoons?provider=NAVER&perPage=100`;
        
              // 첫 번째 요청을 보내 전체 웹툰 수를 파악
              const initialResponse = await fetch(apiURL + `&page=1`, {
                method: "GET",
                headers: {
                  "Content-Type": "application/json",
                },
              });
              if (!initialResponse.ok) {
                throw new Error("Network response was not ok");
              }
              const initialData = await initialResponse.json();
              const totalWebtoons = initialData.total; // 총 웹툰 개수
              const perPage = 100; // 페이지당 웹툰 개수
              const totalPages = Math.ceil(totalWebtoons / perPage); // 전체 페이지 수 계산
        
              // 모든 페이지의 요청을 생성
              const requests = [];
              for (let page = 1; page <= totalPages; page++) {
                requests.push(fetch(apiURL + `&page=${page}`, {
                  method: "GET",
                  headers: {
                    "Content-Type": "application/json",
                  },
                }).then(response => response.json()));
              }
        
              // 모든 요청을 병렬로 실행하여 결과를 모음
              const results = await Promise.all(requests);
              const allWebtoons = results.flatMap(result => result.webtoons); // 모든 웹툰 데이터를 하나의 배열로 합침
        
              setFilteredWebtoons(allWebtoons); // 상태에 저장하여 렌더링
            } catch (error) {
              console.error("There was a problem with the fetch operation:", error);
            } finally {
              setLoading(false);
            }
          };
        
          fetchAllWebtoons();
        }, []);

         

        결과

        해결 후

        console에 allWebtoons를 확인해보면 전체 웹툰 목록을 가져온 것을 볼 수 있다.

        'Web Frontend' 카테고리의 다른 글

        Recoil 새로고침 랜더링 문제  (0) 2024.08.03
        react-Intersection-Observer 라이브러리를 이용해 무한스크롤 구현하기  (0) 2024.08.02
        ThemeProvider로 theme.ts에서 디자인 시스템 설정하기  (0) 2024.07.10
        IntersectionObserver를 활용한 Lazy Loading 적용  (0) 2024.06.23
        웹 성능 최적화: 이미지 및 폰트 최적화  (0) 2024.06.07
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바