stale-while-revalidate(SWR), Background refetches

강정우·2024년 4월 29일
0

next.js

목록 보기
9/9

stale-while-revalidate

stale response

클라이언트는 서버로부터 API를 통해 데이터를 받아온다.
데이터가 클라이언트에 한 번 전해진 이상, 클라이언트는 해당 데이터가 최신 데이터인지 더 이상 알 수가 없다.
이렇게 서버에서 클라이언트로 전해져 최신 데이터인지 알 수 없는, 즉 신선함을 잃은 데이터를 stale response 라고 한다.

swr 전략

stale-while-revalidate는 '캐싱 전략'의 일종이다. (아직 비표준 단계의 HTTP Cache-Control)
swr 전략은 캐싱된 컨텐츠를 즉시 로드하는 즉시성과 업데이트된 캐싱 컨텐츠가 미래에 사용되도록 보장하기 위한 디렉티브이다.

데이터가 stale response인지 아닌지는 Cache-Control 헤더에 함께 포함된 max-age를 기준으로 캐싱된 컨텐츠의 최신 상태 여부를 판단하게 되는데, swr은 캐싱된 낡은 컨텐츠에 대한 확장된 지시를 표현한다.

Cache-Control: max-age=600, stale-while-revalidate=30

캐싱 동작 과정

위와 같은 HTTP 해더는 캐싱된 컨텐츠에 대해 아래와 같이 지시를 따르게 된다.

1. 캐싱된 데이터가 아직 최신 상태라면 해당 데이터를 그대로 응답

HTTP 요청이 1초(max-age) 이내에 반복적으로 발생한다면, 유효성 검증 없이 캐싱된 컨텐츠를 반환.

2. 만약 1 ~ 60 라면 재검증을 통해 응답

HTTP 요청이 1 ~ 60초(max-age ~ swr) 사이에 반복적으로 발생할 경우, 우선 캐싱된 낡은 컨텐츠를 반환하고, 이와 동시에 캐싱된 컨텐츠를 새로운 컨텐츠로 채우도록 '재검증(revalidate)' 요청이 발생.

이 때, 새로 가져온 데이터가 이전에 캐시된 데이터와 동일한지를 검증하여 아니라면 캐시를 갱신.

3. 60 초 라면 그냥 재요청

HTTP 요청이 60초(swr ~) 이후 시점에 발생한다면, 요청이 서버로 전달되어 컨텐츠를 반환.

이때, max-age 뿐만 아니라 stale-while-revalidate 값보다도 오래된 'truly' stale 데이터라면
stale-while-revalidate 는 동작을 멈추고 (캐싱된 데이터를 사용하지 않고) 그냥 서버에 새로 요청을 보낸다.

즉시성과 최신성 사이의 균형을 맞추기 위해 고안된 방법이다.

다른 캐싱 전략

1. Cache-First

캐싱된 데이터가 존재한다면 요청에 대한 응답은 무조건 캐시에서 보낸다.

만약 캐싱된 데이터가 존재하지 않는다면 API 요청을 보내 응답한다.
그리고 해당 응답은 캐싱되어, 다음 요청이 오면 캐시에서 응답을 보내게 된다.

2. Network-First

기본적으로 항상 API로 최신 데이터를 가져온다.

성공적으로 요청이 응답되면, 해당 응답을 캐싱해놓는다.
만약 요청이 실패하면 캐싱된 데이터가 보내진다.

3. Network-Only

캐시를 사용하지 않고 무조건 API를 찌른다.

4. Cache-Only

무조건 캐시에서만 데이터를 가져온다.

와 같은 다양한 캐싱 전략들을 사용한다고 함.

RFC 5861 문서를 보면 stale-while-revalidate와 함께 제안된 Cache-Control 헤더 중에 stale-if-error같은 것도 있다고 한다.

Incremental Static Regeneration (증분 정적 재생성)

next.js 에서 주로 사용되는 개념으로, next.js에서는 애플리케이션을 빌드할 때 getStaticProps 를 통해 필요한 서버 데이터를 받아와 json 파일로 저장하고, 마크업 파일을 생성해 두어 요청 시 정적으로 빠르게 페이지를 제공한다.

이를 정적 사이트 생성(static site generation) 이라고 한다.

이 기능은 정적 사이트 생성의 이점을 유지하면서도, 실시간 데이터 업데이트의 유연성을 제공한다.

ISR을 통해 개발자는 정적 페이지를 빌드 타임에 미리 생성할 수 있으며, 동시에 정해진 주기 또는 트리거에 따라 필요한 페이지를 재생성할 수 있다.

하지만 빌드 시점에 미리 서버 데이터를 받아와 저장을 하다보니, 특정 시점에서 캡쳐된 데이터가 최신화 데이터로서 무효할 수 있다.

여기서, 넥스트는 잘 알려진 swr 전략을 취해 증분 정적 재생성(incremental static regeneration)을 가능케하여 이러한 문제를 해결한다.

증분 정적 재생성 타임라인은 swr 전략과 동일하다. 재평가 시간 이내의 페이지 요청은 빌드해 두었던 페이지와 데이터를 정적으로 빠르게 제공하고, 이후 재검증을 통해 페이지와 데이터를 재생성하여 최신화한다. 이로서 이후 요청에 대해서는 업데이트된 페이지와 데이터 또한 정적으로 빠르게 제공할 수 있게 된다.

ISR의 작동 원리

1. 빌드 타임에 페이지 생성

애플리케이션의 빌드 과정에서 정적 페이지가 생성된다. 이 페이지들은 서버나 CDN에 저장되어 빠르게 제공될 수 있다.

2. 재생성 트리거

개발자는 특정 페이지를 재생성하기 위한 조건을 설정할 수 있다.
예를 들어, 특정 시간 간격 후에 페이지를 업데이트하거나, API 호출을 통해 새로운 데이터가 있을 때 페이지를 재생성할 수 있다.

3. 백그라운드 업데이트

사용자가 페이지에 접근하면, 먼저 캐시된(또는 미리 생성된) 최신 버전의 페이지가 즉시 제공된다. 만약 페이지가 재생성 조건을 충족한다면, 서버는 백그라운드에서 해당 페이지를 새로운 데이터로 업데이트하고, 다음 요청부터는 업데이트된 페이지를 제공한다.

4. 무중단 서비스 제공

이 과정은 사용자의 경험을 방해하지 않으면서도 최신 데이터를 반영한 페이지를 제공할 수 있게 해준다.
사용자는 페이지 재생성 과정을 기다리지 않고, 즉시 이전에 생성된 페이지를 볼 수 있다.

ISR의 장점

1. 성능 개선

정적 파일을 제공함으로써 서버의 부하를 줄이고 빠른 로딩 시간을 보장한다.

2. 스케일 용이성

정적 파일은 CDN을 통해 쉽게 배포되고 캐시될 수 있어, 트래픽이 급증하는 상황에서도 안정적인 서비스 제공이 가능하다.

3. 실시간 데이터 반영

데이터가 변경되었을 때 자동으로 페이지를 업데이트함으로써 사용자에게 최신 정보를 제공할 수 있다.

4. 개발 유연성

정적 페이지의 장점과 서버 사이드 렌더링의 동적인 데이터 처리 능력을 결합하여 개발자에게 더 큰 유연성을 제공한다.

사용 사례

ISR은 뉴스 웹사이트, 블로그, 이커머스 플랫폼 등 다양한 유형의 웹 애플리케이션에 적합하다.
특히, 자주 업데이트되어야 하는 콘텐츠를 갖고 있는 사이트에서 유용하게 사용될 수 있다.
사용자는 항상 최신 정보를 볼 수 있고, 사이트 소유자는 높은 성능과 효율적인 콘텐츠 관리를 경험할 수 있다.

  • 그럼 왜이렇게 정적 생성을 중하게 생각할까?

정적 생성을 지향했던 이유

정적 생성된 페이지는 클라이언트의 요청 시 상당히 빠르게 제공된다.
빌드 시 생성한 마크업과 데이터가 담긴 json을 제공하기 때문인데, 이는 Time to First Byte (TTFB)를 크게 줄일 수 있을 뿐만 아니라, First Input Delay (FID)와 같은 Web Vital Score를 개선하는 데 큰 도움이 된다.

참고로 좋지 못한 네트워크 상에서는 SSR은 초 단위로 측정되는데 반해 SSG는 밀리 초 단위로 측정된다.

Background refetches

웹 애플리케이션에서 사용자가 대용량 파일을 다운로드해야 하는 경우, 다운로드가 완료되려면 사용자가 페이지에 계속 연결되어 있어야 한다는 문제가 종종 발생한다.
연결이 끊어지면 탭을 닫거나 다운로드가 중지되는 페이지에서 다른 곳으로 이동한다.

웹 개발자가 사용자가 비디오 파일을 다운로드하기 위해 버튼을 클릭할 때와 같이 백그라운드에서 일부 가져오기(fetch)를 수행하도록 브라우저에 지시하는 방법을 만든다. 그러면 브라우저는 사용자가 볼 수 있는 방식으로 가져오기(fetch)를 수행하여 사용자에게 진행 상황을 표시하고 다운로드를 취소하는 방법을 제공한다. 다운로드가 완료되면 브라우저는 서비스 워커를 열고, 이 시점에서 애플리케이션은 필요한 경우 응답을 통해 무언가를 수행할 수 있다.

Background Fetch API는 사용자가 오프라인 상태에서 프로세스를 시작하면 가져오기(fetch)를 수행할 수 있도록 한다. 연결되면 프로세스가 시작된다. 사용자가 오프라인 상태가 되면 사용자가 다시 켜질 때까지 프로세스가 일시 중지된다.

reference

https://youthfulhps.dev/nextjs/next-isr/#%EC%A6%9D%EB%B6%84-%EC%A0%95%EC%A0%81-%EC%9E%AC%EC%83%9D%EC%84%B1%EC%9D%98-%ED%83%80%EC%9E%84%EB%9D%BC%EC%9D%B8

profile
智(지)! 德(덕)! 體(체)!

0개의 댓글