Computer >> 컴퓨터 >  >> 프로그램 작성 >> Redis

Redis로 Next.js 애플리케이션 속도 향상

Next.js는 서버 측 렌더링과 정적 사이트 생성을 함께 제공하는 매우 성공적인 웹 프레임워크입니다. SSG는 CDN 캐싱 덕분에 웹 사이트 속도를 높이고 SSR은 SEO 및 동적 데이터를 지원합니다.

서버 측 렌더링은 전체 스택 응용 프로그램을 작성하는 데 도움이 되는 훌륭한 기능입니다. 그러나 주의하지 않으면 Next.js 웹사이트의 성능이 쉽게 영향을 받을 수 있습니다. 이 블로그 게시물에서는 Redis를 활용하여 Next.js API 호출 속도를 높이는 방법을 설명합니다. 그 전에 성능을 향상시키는 더 간단한 방법을 간단히 언급하겠습니다.

API 호출에 SWR 사용

SWR은 매우 스마트한 데이터 가져오기 라이브러리입니다. HTTP RFC 5861에 설명된 HTTP 캐시 무효화 전략(stale-while-revalidate)을 사용합니다. SWR로 API를 호출하면 캐시된 데이터를 즉시 반환하지만 비동기적으로 현재 데이터를 가져와 UI를 업데이트합니다. 또한 staleness에 대한 내성에 따라 refreshInterval을 설정할 수도 있습니다.

const { data: user } = useSWR('/api/user', { refreshInterval: 2000 })

위 코드에서 사용자 API는 2초마다 새로고침됩니다.

Redis로 캐싱

SWR은 매우 간단하고 효과적입니다. 그러나 서버 측 캐싱이 필요한 경우가 있습니다.

  • 클라이언트 측 캐싱은 클라이언트의 성능을 향상시킵니다. 그러나 클라이언트 수가 많으면 서버 측 리소스에 높은 로드가 발생하여 결국 클라이언트 측 성능에도 영향을 미칠 수 있습니다.
  • 할당량이 있는 외부 API를 사용하는 경우 서버 측에서 API 사용을 제어하고 싶을 것입니다. 그렇지 않으면 너무 많은 클라이언트가 API를 빠르게 사용하게 됩니다.
  • 동적 입력을 사용하여 서버 측에서 리소스를 계산, 가져오기 또는 처리한 경우 클라이언트 측 캐싱은 그다지 유용하지 않습니다.

예시 프로젝트:Covid Tracker

이 프로젝트에서는 Javier Aviles의 Covid API를 사용하여 가장 많은 사례가 있는 상위 10개 국가를 찾습니다. 웹사이트와 소스코드를 확인하세요.

다음과 같이 Redis를 사용하여 Covid API의 응답을 캐시합니다.

  • 응답이 훨씬 빠릅니다. 웹사이트를 확인하면 Covid API를 호출하는 데 수백 밀리초가 걸리는 반면 Redis에서 가져오는 데 1-2밀리초가 걸린다는 것을 알 수 있습니다.
  • 너무 많은 요청으로 Covid API를 압도하지 않을 것입니다.

API 코드

코드는 먼저 Redis에 캐시된 API 결과가 있는지 확인합니다. 그렇지 않은 경우 Covid API에서 모든 국가 목록을 가져와 현재 날짜의 사례 수로 정렬하고 상위 10개를 Redis에 저장합니다. Redis에 저장하는 동안 "EX" 60 매개변수를 설정합니다. 이는 Redis가 60초 내에 항목을 제거한다는 것을 의미합니다.

import Redis from "ioredis";

let redis = new Redis(process.env.REDIS_URL);

export default async (req, res) => {
  let start = Date.now();
  let cache = await redis.get("cache");
  cache = JSON.parse(cache);
  let result = {};
  if (cache) {
    console.log("loading from cache");
    result.data = cache;
    result.type = "redis";
    result.latency = Date.now() - start;
    return res.status(200).json(result);
  } else {
    console.log("loading from api");
    start = Date.now();
    return fetch("https://coronavirus-19-api.herokuapp.com/countries")
      .then((r) => r.json())
      .then((data) => {
        data.sort(function (a, b) {
          return b.todayCases - a.todayCases;
        });
        result.data = data.splice(1, 11);
        result.type = "api";
        result.latency = Date.now() - start;
        redis.set("cache", JSON.stringify(result.data), "EX", 60);
        return res.status(200).json(result);
      });
  }
};

UI 코드

UI는 간단한 React 코드입니다. SWR을 사용하여 API에서 데이터를 가져옵니다.

export default function Home() {
  function refresh(e) {
    e.preventDefault();
    window.location.reload();
  }
  const { data, error } = useSWR("api/data", fetcher);
  if (error) return "An error has occurred.";
  if (!data) return "Loading...";
  return (
    <div className={styles.container}>
      <Head>
        <title>Covid Tracker</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>Covid Tracker</h1>

        <p className={styles.description}>
          Top 10 countries with the most cases today
        </p>

        <div className={styles.grid}>
          <div className={styles.card} onClick={refresh}>
            <table className={styles.table}>
              <thead>
                <tr>
                  <th>Country</th>
                  <th>Today Cases</th>
                  <th>Today Deaths</th>
                </tr>
              </thead>
              <tbody>
                {data.data.map((item) => (
                  <tr>
                    <td>{item.country}</td>
                    <td>{item.todayCases}</td>
                    <td>{item.todayDeaths}</td>
                  </tr>
                ))}
              </tbody>
            </table>
            <br />
            <em>
              Loaded from {data.type} in <b>{data.latency}</b> milliseconds.
              Click to reload.
            </em>
          </div>
        </div>
      </main>

      <footer className={styles.footer}>
        This is a sample project for the blogpost &nbsp;
        <a
          href="https://blog.upstash.com/nextjs-caching-with-redis"
          target="_blank"
          rel="noopener noreferrer"
        >
          Speed up your Next.js application using Serverless Redis for caching.
        </a>
      </footer>
    </div>
  );
}

https://swr.vercel.app/docs/with-nextjs

https://brianlovin.com/writing/caching-api-routes-with-next-js

https://coronavirus-19-api.herokuapp.com/countries

https://github.com/javieraviles/covidAPI