요약

SSG페이지로 만든 뒤 업데이트하기 위해 revalidate를 아무리 짧게줘도 1시간 뒤에 이미지가 만료되는 현상이 발견됐다.

 

알고보니 revalidate 시간 동안은 이미 만들어진 static page를 전송해주고 revalidate 시간을 넘어 새로운 요청이 들어와야 새 정적 페이지를 만들어준다. 예를 들면 처음 빌드하고 페이지를 방문한 뒤 revalidate를 1분으로 짧게줘도 그 사이에 다른 누군가가 방문하지 않았고 1년이 지났다면 1년 뒤 처음 접속한 유저는 내가 아무리 블로그 글을 갱신했더라도 1년전 봤던 페이지와  같다는 것이다. 그리고 NextJS는 그제서야 revalidate 시간을 확인하고 새로 빌드해주게 된다. 아무래도 잦은 빌드시 성능적으로 비효율적이기 때문에 그런거같다.

 

두 가지 방법이 있었는데 전체 페이지를 SSG로 사용하기 위해 vercel의 Deploy hooks를 사용해 매 시간마다 강제 재빌드할 수 있도록 설정하였습니다.

 

문제

일전에 블로그 개발을 진행하면서 이미지가 만료되어 이미지가 보이지 않는 현상이 있었고 ISR을 통해 문제를 해결했었습니다.

 

SSG를 업데이트하기 위한 증분 정적 재생(ISR)

개요 앞선 내용과 이어지는 내용입니다! https://choiblog.tistory.com/2 SSG, SSR의 차이점을 문제를 통해 확실히 정리 요약 노션을 사용한 블로그 개발을 Nextjs로 진행하던 중 초기 Notion API를 사용하는 부

choiblog.tistory.com

이때 ISR을 도입하면서 문제를 해결한 줄 알았지만 해당 부분을 잘못 알고 사용했었고 또 다시 이미지가 만료되는 현상이 있었습니다. 이때 ISR을 써도 왜 이미지가 만료되는지 찾아보았고 공식문서를 통해 이유를 찾을 수 있었습니다.

 

 

 

Data Fetching: Incremental Static Regeneration | Next.js

Learn how to create or update static pages at runtime with Incremental Static Regeneration.

nextjs.org

문제 해결 과정

On-demand

엄청 삽질을 했고 결국 찾아낸 결과를 스스로 잘못알고 있었다고 생각을한 뒤 on-demand로 구현해보고자 시도하였습니다.

 

Vercel + Github Action으로 노션 Cron Job 만들기

2 . 빌드 결과물을 갱신하기 어렵다. Next.js 에서 revalidate 라는 속성을 제공해서 1분, 30초 단위로 빌드 결과물을 갱신할 수 있도록 하지만 정확히 얘기해서 이건 cron job이 아니라 사용자가 방문한

edge.indegser.com

 

찾아본 결과 NextJS에서 새롭게 빌드해주는 revalidate 트리거를 pages/api에 revalidate로 만든 뒤 해당 페이지로 접근했을 때 요청한 페이지를 새롭게 빌드시켜주게 됩니다.

 

import { NextApiRequest, NextApiResponse } from 'next';

// pages/api/revalidate.js
export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  // Check for secret to confirm this is a valid request
  if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
    return res.status(401).json({ message: 'Invalid token' });
  }

  try {
    // this should be the actual path not a rewritten path
    // e.g. for "/blog/[slug]" this should be "/blog/post-1"
    await res.revalidate('/path-to-revalidate');
    return res.json({ revalidated: true });
  } catch (err) {
    // If there was an error, Next.js will continue
    // to show the last successfully generated page
    return res.status(500).send('Error revalidating');
  }
}
https://<your-site.com>/api/revalidate?secret=<token>

이렇게 라우팅된 주소로 요청을 보내게 되면 누군가 접속하지 않아도 업데이트를 수행하게 되며 revalidate 시간을 넓게줘도 요청에 따랄 강제로 수행하게 됩니다. 하지만 단점으로는 요청 하나에 페이지 정보를 넣어 한개의 페이지만 업데이트 될 수 있다는 것이었고 모든 페이지를 업데이트 하기 위해선 페이지 수만큼의 요청이 필요했습니다. 하지만 vercel의 web hook을 통해서는 하루의 하나 한번의 요청만을 보낼 수 있었고 전체 페이지를 빌드하기 1시간마다 만료없이 빌드하기 위해선 어려울거라고 생각해 cron 작업을 하는 라이브러리를 찾아보았습니다.

 

QStash & vercel Deploy hook

 

Upstash: Serverless Data for Redis® and Kafka®

Designed for the serverless with per-request pricing and Redis®/Kafka® API.

upstash.com

vercel webhook 문서에 더 빈번한 요청을 위해 사용할 수 있는 방안을 제시해주었습니다. 하지만 free tier에서는 요청 횟수가 500회로 정해져있었고 10개 정도되는 개별 페이지를 한 시간마다 요청해서 작업하는 것도 매우 횟수가 많은데 여기에 동적인 페이지 주소 정보를 설정하는 것 등 매우 어렵다고 생각을 했고 대안책을 찾게 되었습니다

 

Deploy Hooks

다행히도 vercel에서 제공해주는 Deploy hook이 있었고 깃허브 브랜치와 연동해서 설정해둔 브랜치를 시간마다 계속해서 빌드할 수 있도록 api 요청을 보내는 cron 작업을 설정하였습니다.

 

Deploy Hooks

Deploy Hooks allow you to create URLs that accept HTTP POST requests to trigger deployments. Each URL correspond to a branch of a GitHub or GitLab repository linked to the project.

vercel.com

 

회고

매 시간마다 빌드를 다시 한다는 것이 성능적으로 조금 문제가 있지 않을까하는 생각을 하기도 하였지만 이슈 해결이 먼저라고 생각했고 개인적으로는 NextJS에서 자체적으로 만들어주었으면 하는 생각을 하긴했지만 빠르게 발전하는 개발환경 상 금방 또  만들어지지 않을까하고 생각되긴 하였습니다.

 

또 어떤 기능을 구현하면서 문서를 읽어볼 때 사이드 이펙트는 뭔지, 내가 원하는 동작이 정상적으로 수행되는지 꼼꼼히 테스트 해봐야한다는 것을 깨달았습니다. 아무래도 한번 해결한 문제다보니 내가 잘못 설정했는지 등을 확인하는 시간도 많이 걸려서 상당히 답답했고 괜히 나만 이렇게 시간을 오래 쓰면서 개발 실력이 안늘어나는게 아닐까하는 불안감도 들었지만 이런 것도 개발 과정 중 하나라고 생각하면서 꾸준히 개발하자고 마음속으로 생각하는 시간이 되었습니다

복사했습니다!