대부분의 소프트웨어 애플리케이션은 어떤 방식으로든 데이터를 처리하고 처리하도록 설계되어 있습니다. 이러한 프로그램이 점점 더 커지고 복잡해짐에 따라 처리해야 하는 데이터의 양이 점점 더 방대해질 수 있습니다. 이렇게 방대한 데이터 세트를 부적절하게 관리하면 해당 애플리케이션의 성능이 최적화되지 않을 수 있습니다.

원활한 사용자 경험을 제공하기 위해서는 애플리케이션 성능을 최적화하는 것이 중요하며, 이 목표를 달성하기 위해 여러 가지 접근 방식을 사용할 수 있습니다. 페이지 매김과 무한 스크롤링이 그 중 두 가지 방법입니다. 이러한 기술을 사용하면 데이터 렌더링을 효율적으로 처리하는 동시에 제품에 대한 전반적인 사용자 만족도를 높일 수 있습니다.

TanStack 쿼리를 사용한 페이지 매김 및 무한 스크롤링

TanStack 쿼리 —은 React 쿼리 —를 변형한 JavaScript 애플리케이션을 위한 강력한 상태 관리 라이브러리입니다. 캐싱과 같은 데이터 관련 작업을 포함한 여러 기능 중에서도 애플리케이션 상태 관리를 위한 효율적인 솔루션을 제공합니다.

페이지 매김 프로세스는 방대한 데이터 세트를 이해하기 쉬운 작은 부분으로 나누어 사용자가 버튼과 같은 탐색 컨트롤을 활용하여 정보에 점진적으로 액세스할 수 있도록 합니다. 반면에 무한 스크롤은 보다 유동적이고 자연스러운 탐색 환경을 제공하는 대안적인 접근 방식을 제시합니다. 페이지를 스크롤할 때 사용자의 명시적인 명령이나 동작 없이도 새로운 데이터가 로드되고 표시됩니다.

상당한 양의 정보를 다룰 때 페이지 매김과 무한 스크롤은 이러한 데이터를 사용자 친화적인 방식으로 관리하고 표시하기 위한 효과적인 전략으로 활용됩니다. 그러나 어떤 접근 방식이 가장 적합한지 결정하는 것은 궁극적으로 당면한 애플리케이션의 특정 요구 사항에 달려 있습니다.

이 프로젝트의 소스 코드는 GitHub에서 사용할 수 있으며, 앞서 언급한 리포지토리를 통해 액세스할 수 있습니다.

Next.js 프로젝트 설정하기

프로세스를 시작하려면 Next.js 프로젝트를 설정해야 합니다. 여기에는 프레임워크 내에서 “App” 디렉터리를 사용하는 Next.js 13의 최신 반복을 가져와 설치하는 것이 포함됩니다.

 npx create-next-app@latest next-project --app 

npm을 사용하여 프로젝트 내에 TanStack 패키지를 설치하려면 Node 패키지 관리자를 사용합니다.

 npm i @tanstack/react-query 

Next.js 애플리케이션에 TanStack 쿼리 통합

Next.js 프로젝트 내에 TanStack 쿼리를 통합하려면 애플리케이션의 루트, 특히 layout.js 파일 내에 TanStack 쿼리의 새 인스턴스를 설정하고 초기화해야 합니다.탄스택 쿼리에서 쿼리클라이언트와 쿼리클라이언트프로바이더를 모두 가져와서 이를 수행할 수 있습니다. 그런 다음, 다음과 같이 구조화된 QueryClientProvider 내에 자식 프로퍼티를 포함시켜야 합니다:

 "use client"
import React from 'react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
};

export default function RootLayout({ children }) {
  const queryClient = new QueryClient();

  return (
    <html lang="en">
      <body>
        <QueryClientProvider client={queryClient}>
          {children}
        </QueryClientProvider>
      </body>
    </html>
  );
}

export { metadata };

이 구성을 구현하면 애플리케이션의 현재 상태에 대한 탄스택 쿼리의 포괄적인 가용성을 보장할 수 있습니다.

사용 쿼리 훅을 사용하여 페이지 매김 구현

`사용 쿼리` 훅을 활용하면 데이터 검색 및 관리에 대한 원활한 접근 방식이 가능합니다. 개별 페이지 번호와 같은 페이지 매김 매개변수를 통합하면 원하는 정보 부분에 손쉽게 액세스할 수 있습니다.

이 글도 확인해 보세요:  HTTP와 HTTPS: 차이점은 무엇인가요?

또한, 제공된 후크는 사용자의 선호도에 따라 데이터 검색 프로세스를 맞춤화할 수 있는 다양한 개인 설정 및 구성을 제공합니다. 여기에는 로딩 상태를 효과적으로 관리할 수 있을 뿐만 아니라 캐시 설정을 설정하는 기능도 포함됩니다. 이러한 기능을 활용하면 원활한 페이지 매김 인터페이스를 손쉽게 구축할 수 있습니다.

Next.js 애플리케이션 내에 페이지 매김을 통합하려면 “src/app” 디렉터리 내에 “Pagination/page.js” 파일을 생성합니다. 이 파일 내에 후속 가져오기 문을 포함합니다:

 "use client"
import React, { useState } from 'react';
import { useQuery} from '@tanstack/react-query';
import './page.styles.css';

그런 다음 React 함수형 컴포넌트를 정의합니다. 이 컴포넌트 내부에서 외부 API에서 데이터를 가져오는 함수를 정의해야 합니다. 이 경우 JSONPlaceholder API 을 사용하여 게시물 집합을 가져옵니다.

 export default function Pagination() {
  const [page, setPage] = useState(1);

  const fetchPosts = async () => {
    try {
      const response = await fetch(`https://jsonplaceholder.typicode.com/posts?
                                  _page=${page}&_limit=10`);

      if (!response.ok) {
        throw new Error('Failed to fetch posts');
      }

      const data = await response.json();
      return data;
    } catch (error) {
      console.error(error);
      throw error;
    }
  };

  // add the following code here
}

`useQuery` 훅은 GraphQL 쿼리를 사용하여 API에서 데이터를 가져올 수 있는 React 훅입니다. 쿼리 문자열, 변수, 응답 데이터를 처리하는 리졸버 함수와 같은 여러 매개변수를 받습니다. 이러한 매개변수는 후크에 인자로 전달되는 별도의 객체로 지정할 수 있습니다. 예를 들어 다음과 같이 작성할 수 있습니다: ”’자바스크립트 import { useQuery } from ‘react-query’; const myData = useQuery(‘myApi’, { 쿼리: ‘{ 나 { 이름 } }’, }, () => ({ // 여기서 성공적인 결과 처리 })); “`

   const { isLoading, isError, error, data } = useQuery({
    keepPreviousData: true,
    queryKey: ['posts', page],
    queryFn: fetchPosts,
  });

`keepPreviousData` 속성을 `true`로 설정하면 애플리케이션이 새 데이터를 가져올 때 이전에 검색된 정보를 유지할 수 있습니다. 쿼리 키` 속성은 엔드포인트 및 요청 중인 특정 페이지와 같이 조회에 사용되는 키 모음으로 구성됩니다. 최종적으로 `queryFn` 요소는 `fetchPosts`라는 함수를 통해 데이터를 획득하는 프로세스를 시작합니다.

앞서 언급한 후크는 데이터 검색 단계에서 적절한 인터페이스를 렌더링하여 사용자 경험을 향상시키기 위해 배열이나 객체를 분해하는 과정과 유사하게 추출할 수 있는 일련의 상태 변수를 제공합니다. 이러한 상태에는 isLoading, isError 등이 포함됩니다.

이 기능을 구현하기 위해서는 연속 작동의 현재 상태에 따라 다양한 메시지 화면을 표시하는 코드를 통합해야 합니다.

   if (isLoading) {
    return (<h2>Loading...</h2>);
  }

  if (isError) {
    return (<h2 className="error-message">{error.message}</h2>);
  }

1. 사용자에게 데이터가 대화형 방식으로 표시되는 방식을 시각적으로 표현합니다. 2. 개발자와 디자이너가 프로덕션 환경에 배포하기 전에 작업을 미리 보고 테스트할 수 있습니다.

`useQuery` 훅을 사용하여 지정된 API에서 콘텐츠를 검색하면 이후 “데이터” 변수로 알려진 지정된 저장소에 저장됩니다. 이 컨테이너는 소프트웨어 시스템의 내부 작동을 조절하는 역할을 합니다. 결과적으로, 상기 저장소 내에 축적된 게시물의 누적 카탈로그를 처리하는 반복 프로세스를 통해 순회할 수 있으며, 궁극적으로 사용자 인터페이스 상에 시각적으로 표현될 수 있습니다.

이 글도 확인해 보세요:  개발자와 디자이너를 위한 10가지 UI/UX 영감 사이트

페이지가 매겨진 추가 정보에 대한 사용자 액세스를 용이하게 하기 위해, 애플리케이션 내에 “이전” 및 “다음” 버튼으로 구성된 일련의 탐색 도구를 통합할 것을 제안합니다. 이러한 버튼을 통해 사용자는 각각의 옵션을 클릭하기만 하면 여러 페이지의 콘텐츠를 원활하게 탐색할 수 있습니다. 이러한 구현은 사용자가 각 페이지를 개별적으로 수동으로 검색하거나 로드할 필요 없이 추가 데이터를 쉽게 검색할 수 있어 사용자에게 향상된 탐색 환경을 제공할 것입니다.

   return (
    <div>
      <h2 className="header">Next.js Pagination</h2>
      {data && (
        <div className="card">
          <ul className="post-list">
            {data.map((post) => (
                <li key={post.id} className="post-item">{post.title}</li>
            ))}
          </ul>
        </div>
      )}
      <div className='btn-container'>
        <button
          onClick={() => setPage(prevState => Math.max(prevState - 1, 0))}
          disabled={page === 1}
          className="prev-button"
        >Prev Page</button>

        <button
          onClick={() => setPage(prevState => prevState + 1)}
          className="next-button"
        >Next Page</button>
      </div>
    </div>
  );

마지막으로 터미널 또는 명령 프롬프트에서 일련의 명령을 실행하여 개발 서버를 실행하는 프로세스를 시작합니다.

 npm run dev 

웹 브라우저에서 을 방문하세요.

애플리케이션의 디렉토리 구조에 페이지 매김 모듈을 통합하면 Next.js는 이를 지정된 경로로 인식하여 해당 URL을 통해 해당 웹 페이지로 원활하게 이동할 수 있도록 합니다.

무한 스크롤 사용 무한 쿼리 훅 사용

무한 스크롤은 사용자가 계속 스크롤할 때 추가 콘텐츠를 동적으로 로드하여 원활하고 중단 없는 브라우징 환경을 제공합니다. 이 기능은 YouTube와 같은 인기 플랫폼에서 볼 수 있으며, 새로운 동영상 항목이 자동으로 검색되어 중단이나 단절 없이 표시됩니다.

`useInfiniteQuery` 훅을 활용하면 원격 소스에서 데이터를 점진적으로 수집하여 무한 스크롤을 가능하게 하는 동시에 사용자가 아래로 내려갈 때 후속 정보 페이지를 자동으로 가져와서 표시할 수 있습니다.

애플리케이션에 무한 스크롤 기능을 통합하려면 “InfiniteScroll/page.js”라는 새 JavaScript 파일을 생성하여 프로젝트의 “src/app” 디렉터리에 배치해야 합니다. 이 작업이 완료되면 이 파일의 시작 부분에 이 기능을 구현하는 데 필요한 다양한 모듈 또는 컴포넌트에 액세스할 수 있도록 “임포트”라고 하는 여러 임포트 문을 포함시켜야 합니다. 이러한 임포트에는 일반적으로 웹 애플리케이션 내에서 무한 스크롤 기능을 구현하기 위해 특별히 설계된 특정 라이브러리 또는 프레임워크(예: 앞서 언급한 ‘InfiniteScroll’과 같은)가 포함됩니다.

 "use client"
import React, { useRef, useEffect, useState } from 'react';
import { useInfiniteQuery } from '@tanstack/react-query';
import './page.styles.css';

물론이죠! 다음은 React 애플리케이션에서 Redux를 사용해 간단한 상태 관리 시스템을 구현하는 방법의 예시입니다: ”’자바스크립트 // components/PostsList.js ‘react-redux’에서 { useSelector }를 가져옵니다; import { fetchPosts } 를 가져옵니다; const PostsList = () => { const [posts, setPosts] = useState([]); // 컴포넌트가 마운트될 때 썽크 액션 생성자를 호출합니다. useEffect(() => { dispatch(fetchPosts()); }, []); 반환 (

{/* 포스트 목록 렌더링 */} {posts.map((post) => (

  • {post.title

     export default function InfiniteScroll() {
      const listRef = useRef(null);
      const [isLoadingMore, setIsLoadingMore] = useState(false);

      const fetchPosts = async ({ pageParam = 1 }) => {
        try {
          const response = await fetch(`https://jsonplaceholder.typicode.com/posts?
                                      _page=${pageParam}&_limit=5`);

          if (!response.ok) {
            throw new Error('Failed to fetch posts');
          }

          const data = await response.json();
          await new Promise((resolve) => setTimeout(resolve, 2000));
          return data;
        } catch (error) {
          console.error(error);
          throw error;
        }
      };

      // add the following code here
    }

    페이지 매김 솔루션과 달리, 이 구현은 검색 프로세스 중에 2초의 지연 시간을 통합하여 사용자가 스크롤하면서 현재 정보를 숙독할 수 있도록 함으로써 업데이트된 데이터 집합을 새로고침하도록 유도합니다.

    이 글도 확인해 보세요:  내부에서 REST API 호출을 수행하는 방법 VS 코드

    `useInfiniteQuery` 훅은 React 컴포넌트 내에서 무한한 데이터 세트를 검색하고 렌더링하는 효율적인 메커니즘을 가능하게 하는 함수입니다. 컴포넌트를 처음 마운트할 때 이 훅은 서버에서 첫 번째 데이터 세트를 가져오기 위해 초기 페치를 수행합니다. 이후 사용자가 콘텐츠를 스크롤할 때 후크는 후속 데이터 페이지를 동적으로 로드하고 컴포넌트의 디스플레이에 원활하게 통합합니다.

       const { data, fetchNextPage, hasNextPage, isFetching } = useInfiniteQuery({
        queryKey: ['posts'],
        queryFn: fetchPosts,
        getNextPageParam: (lastPage, allPages) => {
          if (lastPage.length < 5) {
            return undefined;
          }
          return allPages.length + 1;
        },
      });

      const posts = data ? data.pages.flatMap((page) => page) : [];

    여러 페이지의 집합 콘텐츠를 활용하여 “posts” 변수를 단일 배열 내에 통합하여 원래 “데이터” 엔티티의 간소화된 표현을 생성합니다. 이 프로세스를 통해 각각의 개별 게시물을 원활하게 탐색하고 쉽게 시각화할 수 있습니다.

    사용자의 스크롤 동작을 모니터링하고 목록의 끝에 가까워질 때 추가 콘텐츠를 동적으로 로드하기 위해, 교차점 관찰자 API를 활용하는 기능을 구현할 수 있습니다. 이를 통해 특정 요소가 화면의 가시 영역에 들어오는 시점을 감지할 수 있습니다.

       const handleIntersection = (entries) => {
        if (entries[0].isIntersecting && hasNextPage && !isFetching && !isLoadingMore) {
          setIsLoadingMore(true);
          fetchNextPage();
        }
      };

      useEffect(() => {
        const observer = new IntersectionObserver(handleIntersection, { threshold: 0.1 });

        if (listRef.current) {
          observer.observe(listRef.current);
        }

        return () => {
          if (listRef.current) {
            observer.unobserve(listRef.current);
          }
        };
      }, [listRef, handleIntersection]);

      useEffect(() => {
        if (!isFetching) {
          setIsLoadingMore(false);
        }
      }, [isFetching]);

    결론적으로 제목, 콘텐츠, 날짜 등의 정보를 각각 포함하는 ‘게시물’ 객체 배열을 렌더링하는 동적 컴포넌트를 만들었습니다.이 컴포넌트는 React 훅을 사용해 상태를 효율적으로 관리하면서 하위 컴포넌트에 컨텍스트 값을 제공합니다. 또한 컴포넌트의 반환문 내에 자바스크립트 표현식을 사용해 조건부 렌더링을 구현했습니다. 마지막으로 이 컴포넌트를 사용할 때 브라우저에서 렌더링되는 JSX 코드를 제공합니다: “`jsx

    {posts.map((post) => (

    {post.title}

    {post.content}

    ))}

       return (
        <div>
          <h2 className="header">Infinite Scroll</h2>
          <ul ref={listRef} className="post-list">
            {posts.map((post) => (
              <li key={post.id} className="post-item">
                {post.title}
              </li>
            ))}
          </ul>
          <div className="loading-indicator">
            {isFetching ? 'Fetching...' : isLoadingMore ? 'Loading more...' : null}
          </div>
        </div>
      );

    변경 사항을 구현한 후 로 이동하여 기능을 직접 확인하시기 바랍니다.

    탄스택 쿼리: 데이터 가져오기 그 이상

    TanStack Query는 페이지 매김 및 무한 스크롤 기능을 지원하여 종합적인 데이터 관리 라이브러리로서의 다용도성을 보여줍니다. 이러한 기능은 다양한 유형의 데이터 조작 작업을 효과적으로 처리할 수 있는 라이브러리의 능력을 보여줍니다.

    이 솔루션이 제공하는 포괄적인 기능 배열을 통해 상태 보존에 대한 효과적인 제어를 포함하여 애플리케이션 데이터 관리 작업을 원활하게 최적화할 수 있습니다. 동시에 다양한 데이터 중심 작업의 간소화된 실행을 통해 웹 애플리케이션 성능과 사용자 만족도를 모두 향상시킬 수 있습니다.

  • By 최은지

    윈도우(Windows)와 웹 서비스에 대한 전문 지식을 갖춘 노련한 UX 디자이너인 최은지님은 효율적이고 매력적인 디지털 경험을 개발하는 데 탁월한 능력을 발휘합니다. 사용자의 입장에서 생각하며 누구나 쉽게 접근하고 즐길 수 있는 콘텐츠를 개발하는 데 주력하고 있습니다. 사용자 경험을 향상시키기 위해 연구를 거듭하는 은지님은 All Things N 팀의 핵심 구성원으로 활약하고 있습니다.