Skip to content

Latest commit

 

History

History
187 lines (129 loc) · 6.21 KB

데이터 로딩, 캐싱, 갱신.md

File metadata and controls

187 lines (129 loc) · 6.21 KB

데이터 로딩, 캐싱 그리고 가져오기

  • 데이터 로딩은 모든 어플리케이션에서 핵심적인 부분임
  • 해당 부분에서는 React, Next.js의 데이터 로딩, 캐싱, 갱신에 대한 방법을 알 수 있음
  • 데이터를 가져오는 방법은 아래 4가지가 존재함
    1. 서버에서 fetch 를 통해 가져오기
    2. 서버에서 외부 라이브러리를 통해 가져오기
    3. 클라이언트에서 Route Handler 를 통해 가져오기
    4. 클라이언트에서 외부 라이브러리를 통해 가져오기

서버에서 fetch 를 통한 데이터 로딩

  • Next.js는 기본적으로 fetch API를 상속받아서 사용중임
  • 해당 기능은 서버에 대한 각 요청에 대해서 캐싱과 갱신을 커스텀 할 수 있음
  • 리액트는 fetch 를 사용해서 React 컴포넌트 트리를 렌더링 하는 동안 가져오기 요청을 자동으로 캐싱함
  • 서버 컴포넌트에서 Route Handler, Server Actions 내부에서 async/await 키워드와 함께 fetch 를 사용할 수 있음
async function getData() {
  const res = await fetch("https://api.example.com/...");
  // 반횐된 값을 직렬화되지 않은 값임.
  // Date, Map, Set 등 데이터 반환이 가능함

  if (!res.ok) {
    // 예외가 발생하는 경우 제일 가까운 error.ts 바운더리가 활성화됨
    throw new Error("Failed to fetch data");
  }

  return res.json();
}

export default async function Page() {
  const data = await getData();

  return <main></main>;
}

데이터 캐싱하기

  • 캐싱은 데이터를 저장해두므로 모든 요청에 대해서 데이터를 또 가져올 필요가 없음
  • 기본적으로 fetch에서 반환된 값을 Data Cache에 자동으로 저장함
  • 빌드타임이나 요청시간에 데이터를 fetch 하고 각 데이터 요청에 재사용이 가능하다는것을 의미함
// 'force-cache'가 기본값임, 수정도 가능함
fetch("https://...", { cache: "force-cache" });

그러나 캐싱에는 예외가 있음
Server Action 또는 Route Handler 내부 HTTP POST 요청은 캐싱하지 않음


데이터 갱신하기

  • 갱신은 기존에 캐싱된 데이터를 삭제하고 새로운 데이터를 가져오는 과정임
  • 데이터가 변경되고 실시간 정보를 확실히 보여주고 싶을때 유용함
  • 갱신 기법은 2가지가 존재함

시간 기반 갱신

  • 지정한 시간이 지나면 저장된 캐시 데이터를 삭제하는 방법
  • 데이터의 변동이 없고 실시간성 데이터가 아닌 경우 유용함
  • 시간 기반으로 데이터를 갱신할려고 할때는 next.revalidate 옵션이나 fetch에다가 시간을 지정한다

정적, 동적 렌더링 차이

  • 정적 렌더링의 경우 여러개의 요청중에서 제일 낮은 시간이 갱신시간이 된다
  • 동적 렌더링의 경우 각 fetch마다 다른 갱신시간을 갖는다

온-디맨드 갱신

revalidatePath

  • 특정 경로에 따라서 데이터를 갱신한다

revalidateTag

  • 특정 태그에 따라서 데이터를 갱신한다
export default async function Page() {
  // fetch 옵션에 tags: string[]을 추가한다
  const res = await fetch("https://...", { next: { tags: ["collection"] } });
  const data = await res.json();
  // ...
}
"use server";

import { revalidateTag } from "next/cache";

export default async function action() {
  // collection 태그를 갱신한다
  revalidateTag("collection");
}

캐싱을 비활성화 하기

  • cache: 'no-store' 옵션을 사용
fetch("https://...", { cache: "no-store" });
  • revalidate: 0 옵션을 사용
fetch("https://...", { next: { revalidate: 0 } });
  • Route Handler 내부에서 HTTP POST 메소드 사용
  • cookies, headers 같은 동적함수 이후에 request 요청하기
  • 맨 위에 const dynamic = 'force-dynamic' 정의하기
  • fetchCache 옵션 지정하기
  • Authorization 이나 Cookie 헤더 사용하는 fetch

요청시 개별 fetch 사용하기

  • fetch 옵션에 {cache: 'no-store'} 를 사용하면 매 요청마다 동적으로 데이터를 가져온다

여러개 요청시 fetch 사용하기

  • 세그먼트 구성 옵션을 활용해서 제어하기
  • 하지만 각 fetch 요청에 대해서 개별로 캐싱 동작을 구성하는것을 권장한다

외부 라이브러리에서 데이터 가져오기

  • 일부 라이브러리(CMS, ORM 등)은 fetch를 지원하지 않음
  • 이런 경우 Route Segment Config Option + cache 함수를 사용해서 캐싱 동작 제어가 가능함
  • 캐싱 동작의 결정적인 원인은 정적인지 동적인지에 따라 다름
  • 정적 : 데이터 요청 결과가 캐싱되고 세그먼트의 일부로 재검증이 가능함
  • 동적 : 데이터 요청의 결과가 캐싱되지 않고, 세그먼트가 렌더링 될때마다 새로 가져옴

예시

  • React의 cache 함수는 데이터 요청에 대해 캐싱이 가능함
  • 만약 revalidate 옵션을 3600으로 설정하면, 1시간 마다 새로운 데이터를 가져온다고 지정하는거임
import { cache } from "react";

export const getItem = cache(async (id: string) => {
  const item = await db.item.findUnique({ id });
  return item;
});
import { getItem } from "@/utils/get-item";

export const revalidate = 3600; // 데이터를 1시간 마다 새로 갱신한다

export default async function Page({ params: { id } }: { params: { id: string } }) {
  const item = await getItem(id);
  // ...
}

CSR 방식에서 라우트 핸들러로 데이터 가져오기

  • 만약 클라이언트 컴포넌트에서 데이터 가져오기가 필요하면, 클라이언트에서 라우트 핸들러 호출이 가능함
  • 라우트 핸들러는 서버에서 동작하고 클라이언트로 데이터를 반환해줌
  • API 토큰 등 중요한 정보를 클라이언트에 노출하지 않으려 할때 유용함

CSR 방식에서 외부 라이브러리로 데이터 가져오기

  • 마찬가지로 SWR 또는 TanStack Query를 활용해서 클라이언트에서 데이터 로딩이 가능함
  • 이런 라이브러리들은 자체적으로 캐싱, 갱신 등 기능을 보유하고있음