Data Caching & Revalidating & Mutating[Next.js]

SnowCat·2023년 4월 26일
0

Next.js

목록 보기
14/16
post-thumbnail

Caching Data

  • 데이터 캐싱은 세그먼트 수준, 또는 요청 수준에서 진행됨
    세그먼트 단계에서의 캐싱은 경료 세그먼트에 사용된 데이터를 캐시하고 재검증하게 됨
    요청단계에서의 캐싱은 리액트에서 함수값을 기억했다 다시 똑같은 함수의 요청이 들어올 때 캐시된 값을 반환하게 됨
  • GraphQL 사용시 GET 요청만이 캐싱되며, POST 요청 사용시 cache() 메서드를 사용해야 함
import { getUser } from "@utils/getUser";

export const preload = (id: string) => {
  void getUser(id);
}
export default async function User({ id }: { id: string }) {
  const result = await getUser(id);
  // ...
}
  • 컴포넌트가 필요한 부분보다 먼저 데이터 패칭을 해야하는 경우 preload 메서드 사용
import User, { preload } from '@components/User';

export default async function Page({
  params: { id },
}: {
  params: { id: string };
}) {
  preload(id);
  const condition = await fetchCondition();
  return condition ? <User id={id} /> : null;
}

Revalidating Data

  • Next.js를 사용하면 전체 사이드 빌드 없이 특정 정적 경로를 업데이트할 수 있음
  • 데이터의 재검증은 시간 간격 또는 데이터 업데이트와 같은 이벤트가 기준이 됨
    시간 간격은 revalidate 옵션을 통해 설정가능하며, 일정 시간이 지난 다음의 요청이 들어올때마다 데이터를 갱신하는 작업을 거치게 됨

Mutating Data

  • 외부 데이터를 받아 컴포넌트를 갱신하기 위해서는 router.refresh() 사용

example

  • 다음과 같은 서버컴포넌트가 있다 해보자.
import Todo from './todo';

interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

async function getTodos() {
  const res = await fetch('https://api.example.com/todos', {
    cache: 'no-store',
  });
  const todos: Todo[] = await res.json();
  return todos;
}

export default async function Page() {
  const todos = await getTodos();
  return (
    <ul>
      {todos.map((todo) => (
        <Todo key={todo.id} {...todo} />
      ))}
    </ul>
  );
}
  • Todo 컴포넌트는 Client Component인데, 이곳에서 fetching을 시도할 시 router.refresh()를 사용해 서버측에서 데이터를 갱신시킬 수 있음
    서버에서 데이터를 갱신해 새로운 Todo data를 가져오게 되며, 데이터가 패칭되도 브라우저 기록과 React state는 변화되지 않음
"use client";

import { useRouter } from 'next/navigation';
import { useState, useTransition } from 'react';

interface Todo {
  id: number;
  title: string;
  completed: boolean;
}

export default function Todo(todo: Todo) {
  const router = useRouter();
  const [isPending, startTransition] = useTransition();
  const [isFetching, setIsFetching] = useState(false);

  // 데이터 변경여부 확인
  const isMutating = isFetching || isPending;

  async function handleChange() {
    setIsFetching(true);
    // 데이터 패칭
    await fetch(`https://api.example.com/todo/${todo.id}`, {
      method: 'PUT',
      body: JSON.stringify({ completed: !todo.completed }),
    });
    setIsFetching(false);
    startTransition(() => {
      // 서버에서 데이터를 새로 가져와 정보를 변경, 이 때 state는 유지됨
      router.refresh();
    });
  }

  return (
    <li style={{ opacity: !isMutating ? 1 : 0.7 }}>
      <input
        type="checkbox"
        checked={todo.completed}
        onChange={handleChange}
        disabled={isPending}
      />
      {todo.title}
    </li>
  );
}

출처:
https://beta.nextjs.org/docs/data-fetching/caching
https://beta.nextjs.org/docs/data-fetching/revalidating
https://beta.nextjs.org/docs/data-fetching/mutating

profile
냐아아아아아아아아앙

0개의 댓글