학습 Next.js - Day 15 / App Router 데이터 페칭, 데이터 캐싱, Request Memoization

이유승·2024년 10월 9일

Next.js 학습

목록 보기
16/27



1. App Router에서의 데이터 페칭

  • App Router가 Page Router에서 많은 것이 달라진 이유는?
    -> Server Component라는 새로운 개념이 도입되었기 때문.
    -> 데이터 페칭도 마찬가지의 이유로 많은 변화가 발생하였다.



Page Router에서의 데이터 페칭

  • SSR, SSG, Dynamic SSG을 구분하는 함수 내부에서 데이터 페칭 작업을 수행했었다.
    -> 이후 페이지 컴포넌트에 Props로 데이터를 넘겨주었다.
    -> Page Router에서는 모든 컴포넌트는 Cilent Component였기에 가능했던 일.
    -> App Router의 Server Component에서는 동일한 방법을 사용할 수가 없다.
    -> Server Component는 클라이언트에서는 동작하지 않기 때문.

  • Page Router 방식의 문제점은, 최상단 Page 컴포넌트에 모든 데이터가 집중되기 때문에 하위 컴포넌트에 Props 방식으로 넘기는 것이 복잡해진다.



App Router에서의 데이터 페칭

  • Server Component를 비동기 함수로 전환하여 사용할 수가 있다.
    -> Cilent Component는 브라우저에서 동일한 동작이 요구되기 때문에, 비동기 방식의 컴포넌트는 메모이제이션 등에서 문제가 발생할 수 있어 비동기 방식의 동작을 권장하지 않는다.

  • Server Component에서 직접 데이터를 불러올 수 있다는 것. 필요한 컴포넌트에서 알아서 데이터 페칭 작업을 수행할 수 있다.
async function RecoBooks() {
  const response = await fetch(
    `${process.env.NEXT_PUBLIC_API_SERVER_URL}/book/random`
  );
  
  if (!response.ok) {
    return <div>오류가 발생했습니다...</div>;
  }

  const recoBooks: BookData[] = await response.json();
  
  return (
    <div>
      {recoBooks.map((book) => (
        <BookItem key={book.id} {...book} />
      ))}
    </div>
  );
}

export default function Home() {
  return (
    <div className={style.container}>
      <section>
        <h3>지금 추천하는 도서</h3>
        <RecoBooks />
      </section>
      <section>
        <h3>등록된 모든 도서</h3>
        <AllBooks />
      </section>
    </div>
  );
}
  • Home 컴포넌트를 비동기 방식으로 전환해도 좋고, 아니면 별도의 비동기 컴포넌트를 생성한 다음 Home에서 호출해도 된다.



Next App에서 환경변수를 사용할때 주의점

  • NEXT_PUBLIC이라는 접두사가 없는 경우, 서버에서만 사용이 가능한 환경변수로 간주된다. 작성시 주의.
    -> NEXT_PUBLIC가 없는 환경변수는 Cilent Component에서 접근이 불가능해지기 때문에, 상황에 맞게 작성하면 된다.



2. App Router의 데이터 캐시Data Cache

  • 새로고침 등이 발생할 때마다 데이터를 새롭게 불러오는 것은 서버 자원을 낭비하는 일이다.
    -> 데이터 캐시 기능을 활용하면, 불필요한 요청 숫자가 줄어들어 서비스의 성능이 크게 개선될 수 있다.



데이터 캐시 기능을 사용하는 방법

  • fetch 메소드를 사용할 때, cache 옵션을 활성화하면 된다. Next에서 데이터 캐시와 관련된 기능들을 fetch에 추가해두었기 때문.

  • 그래서 Axios 라이브러리에서는 사용할 수가 없다.



데이터 캐시 옵션의 종류

force-cache

  • Next.js 14버전까지의 데이터 캐시 기본 옵션.

  • 최초 요청시에는 캐시된 데이터가 없으니, 그냥 넘어간다. 이후 서버에서 데이터를 받아 캐시하고, 그 다음 요청부터는 캐시 데이터를 활용해서 서버에 요청을 보내지 않고 데이터를 반환한다. (이 과정을 MISS - SET - HIT 단계로도 지칭한다.)



no-cache

  • Next.js 15 이상 버전에서 데이터 캐시의 기본 옵션. Next App에서는 기본적으로 데이터 캐싱이 동작하지 않도록 설정되어 있다.



revalidate

  • Page Router의 ISR 방식처럼, 일정 시간을 주기로 캐시를 업데이트한다.

  • 기간이 경과한 캐시는 STALE (상했다) 상태로 간주, 다만 1회에 한하여 그대로 반환한다. 그 이후 서버에서 새 데이터를 받아 SET한다.



tags

  • Page Router의 On-Demand-ISR 방식처럼, 일정 시간을 주기로 캐시를 업데이트한다.



데이터 페칭 로그 기록 남기기

/** @type {import('next').NextConfig} */
const nextConfig = {
  logging: {
    fetches: {
      fullUrl: true,
    },
  },
};

export default nextConfig;
  • Next app 설정에서 logging-fetches-fullUrl을 true로 설정하면 모든 데이터 페칭에 대한 로그가 기록된다.

  • 어떤 요청에 대한 캐시가 동작하는지 여부, 그리고 그 이유까지 로그에 표시된다. 개발시 참고할 것.



3. Request Memoization

  • 데이터 페칭을 최적화 시켜주는 기능. 다양한 컴포넌트에서 발생하는 모든 요청들에서 중복된 부분들을 생략할 수 있게 해준다.
    -> 중복된 API 요청을 하나의 요청으로 통합시켜주는 것.

  • Request Memoization는 우선 첫번째 요청의 응답을 기억해둔다. 그 이후에 동일한 요청이 발생했을 때. 서버에 다시 요청을 넣지 않고, Request Memoization에서 기억된 응답을 돌려준다.



Data Cache와 Request Memoization의 구분

  • Request Memoization은 접속 요청이 종료된 시점에서 자동으로 삭제된다. 하나의 페이가 렌더링 되는 동안에만 유효하다는 것.

  • Data Cache는 서버가 중단되기 전까지 영구적으로 보관된다.



Request Memoization는 왜 존재하는가?

  • 중복된 API 요청 정도는 개발자 선에서 알아서 해결할 수 있다. 그런데 Next.js에서는 굳이 Request Memoization라는 별도의 기능까지 추가해서 이를 대신 해결해주고 있다.

  • 그 이유는, Server Component의 도입으로 데이터 페칭의 방식에 변화가 발생했기 때문.

  • 데이터 페칭을 더 편하게 할 수 있는 것은 장점이지만, 문제는 동일한 요청이 여러 컴포넌트에서 발생하는 경우가 발생할 수 밖에 없다는 단점이 동시에 발현되고 말았다.

  • Page Router에서는 Page에서 모든 데이터를 받아서 내려보내주면 그만이었지만, App Router에서는 각 컴포넌트에서 직접 데이터를 페칭할 수 있게 되었기 때문에 중복된 API 요청이 발생할 가능성이 대단히 높아졌다. 하나의 데이터를 여러 컴포넌트에서 사용하는 상황은 대단히 흔한 것이기 때문.

  • 그래서 Next.js에서는 Request Memoization을 도입하여 중복된 API 호출을 자동으로 최적화해주고 있는 것이다.









00. 강의 소개.

profile
프론트엔드 개발자를 준비하고 있습니다.

0개의 댓글