원문: https://www.gatsbyjs.com/blog/re-introducing-gatsby-a-reactive-site-generator/ - Kyle Mathews
Gatsby Cloud는 이제 1초 만에 CDN에 배포할 수 있습니다. 이는 일반적인 CI/CD 서비스에서 정확히 동일한 Gatsby 사이트를 구축하는 것보다 100배 빠릅니다.
우리는 빠르고, 안전하고 강력한 웹사이트를 구축하는 것을 돕기 위해 2017년에 Gatsby v1을 출시했습니다. 이후 우리는 데이터 레이어(Data layer), 반응형 빌드(Reactive build)와 같은 새롭고 강력한 기능을 계속해서 추가했습니다.
일관되고 표준화된 GraphQL을 통해 제공되는 데이터 레이어는 Contentful, WordPress, Shopify의 데이터를 Gatsby DB로 동기화해 실시간 데이터 변경 스트림에 접근할 수 있게 해줍니다.
반응형 빌드는 GraphQL에 의해 동작합니다. 각 페이지는 GraphQL을 통해 데이터 의존성을 선언합니다. 그다음 데이터가 변경되면 Gatsby Cloud는 무효화된 페이지가 업데이트되도록 합니다.
지난 12개월 동안 Gatsby 팀은 이 아키텍처를 우리의 전담 클라우드 인프라로 이식하고 성능을 최적화하는데 집중해 왔습니다.
오늘날 웹에 콘텐츠를 배포하는 방법 중 이보다 더 빠르고 간단하며 확장 가능한 방법은 없습니다.
우리는 이를 반응형 사이트 생성(Reactive Site Generation)이라고 부르기로 했습니다.
Gatsby Cloud의 모든 Gatsby v4 사이트에 대한 콘텐츠 업데이트 평균 배포 시간은 현재 단 5초입니다.
다음은 콘텐츠 관리 시스템(Content Management System, CMS)과 함께 Gatsby Cloud를 사용하면 어떤지에 대한 예입니다.
프로덕션 웹 사이트를 위한 핫 리로딩(hot reloading)입니다.
사이트 소유자는 사이트 배포를 위해 1초만 있으면 됩니다. 변경 사항을 미리 보거나, CMS에서 뉴스 기사의 오타 수정 사항을 배포하거나, 이커머스(ecommerce) 사이트에 실시간 가격 또는 재고 업데이트가 있을 때 변경 사항을 즉시 적용하는 것이 중요합니다. 이런 경험이 우리가 제공하는 것입니다.
반응형 사이트 생성(Reactive Site Generator, RSG)은 크고 작은 웹 사이트를 어떻게 효율적으로 호스팅하고 업데이트할 것인지에 대한 오래된 문제를 해결하기 위한 새로운 접근 방식입니다. 이 글과 다음에 이어질 글에서는 기존 접근 방식인 정적 사이트 생성기(Static Site Generators, SSG)와 서버 사이드 렌더링(Server-Side Rendering, SSR), 해당 방식의 단점, 그리고 새로운 접근 방식이 필요하다고 생각한 이유에 대해 자세히 설명하고자 합니다.
반응형 프로그래밍(Reactive programming)은 출력이 자동으로 업데이트되도록 설계된 소프트웨어를 말합니다. 따라서 출력 A가 입력 B + C에 의존하고 B 또는 C가 변경되면 A는 자동으로 업데이트됩니다. 이는 입력 업데이트를 수동으로 추적하고 출력 재구축을 예약해야하는 명령형 프로그래밍(imperative programming)과 종종 비교됩니다.
React.js는 반응형 프로그래밍의 좋은 예입니다. 입력, JSX 컴포넌트 그리고 데이터는 React에게 원하는 출력, 즉 DOM을 어떻게 표시할지 알려줍니다. 그러면 React는 그렇게 표시되게끔 해줍니다.
React 및 기타 유사한 최신 JS 컴포넌트 라이브러리들은 jQuery와 같은 이전 명령형 기술에 비해 고성능 웹사이트 및 애플리케이션 구축을 단순화합니다. React 이전에 아무도 이를 구축하지 않은 이유는 변경 사항을 추적하고 DOM에 반영하는 반응형 엔진을 구현하는 것이 어렵기 때문입니다. 자동화된 동작을 상상하는 것은 쉽지만 대체로 구현하기는 매우 어렵습니다.
반응형 프로그래밍의 아이디어는 출력을 자동으로 업데이트하는 데 사용할 수 있습니다. Gatsby Cloud의 경우엔 CDN의 캐시입니다.
현대의 웹사이트들은 거대한 트래픽 급증에도 페이지 로딩 속도가 일관되게 빠르고 강력할 수 있도록 CDN 기술에 크게 의존합니다. CDN은 사이트 에셋을 위한 빠르고 확장 가능한 글로벌 캐시입니다.
그러나 React가 DOM에 업데이트를 반영하는 것과 마찬가지로 CDN을 사용하는 데 있어 어려운 부분은 처음 작성하는 것이 아니라 CMS 또는 이커머스 백엔드에서 데이터 변경이 일어났을 때 빠르게 업데이트해야 한다는 점 입니다.
Gatsby Cloud의 반응형 사이트 생성 구현은 보통 1초 이내에 사이트의 CDN 캐시를 자동으로 업데이트합니다. 이는 프로덕션 웹 사이트를 위한 핫 리로딩입니다. 무엇이든 변경하면 사이트가 자동으로 업데이트됩니다.
저는 벤치마크를 위해 Gatsby가 처리할 수 없다고 가장 많이 여겨지는 사례를 골랐습니다. RSG(Reactive Site Generator)가 이를 어떻게 처리할지 봅시다.
벤치마크는 제품 페이지가 변경된 후 재고량을 업데이트하는 데 걸리는 시간을 측정합니다. 이 사이트는 5,000개의 제품이 있는 이커머스 사이트입니다.
이커머스 사이트의 가장 중요한 기능 중 하나는 최신 재고를 표시해 고객이 상품이 품절되었는지 확인하고 제품을 장바구니에 추가하지 않도록 하는 기능입니다. 때문에 CDN 캐시를 가능한 한 빨리 업데이트하는 것이 중요합니다.
5,000개 제품의 재고량은 Chiselstrike 데이터베이스에 저장됩니다. 벤치마크를 100번 실행할 것이고, 벤치마크를 실행할 때마다 재고량이 업데이트되어 새 재고량이 나타날 때까지 CDN에서 해당 웹 페이지를 계속 다운로드한 다음 시작부터 끝까지 기간을 기록합니다.
저는 Gatsby와 함께 다른 두 가지 일반적인 React 메타 프레임워크인 Next.js와 Remix에서 벤치마크를 구현해 CDN 캐시를 업데이트하기 위한 다양한 기술을 테스트했습니다. 저는 Gatsby와 자주 비교되고 동일한 캐싱 기술을 사용하는 React 메타 프레임워크만 사용했지만 벤치마크 결과는 다른 웹사이트에서도 의미가 있습니다.
첫 번째로 RSG를 사용하는 Gatsby Cloud와 SSG를 사용하는 Netlify의 Gatsby의 벤치마크를 비교하겠습니다.
Netlify, AWS Amplify, Vercel 및 기타 여러 CI/CD 서비스에서 Gatsby는 SSG로 실행됩니다. 즉, 코드 및 데이터 업데이트 모두에 대해 전체 빌드 프로세스를 설정하고 프로비저닝된 리눅스 컨테이너에서 실행해야 합니다.
반면 Gatsby Cloud는 데이터 변경에 즉시 대응할 수 있는 RSG 서비스에 사이트를 구축해 데이터 업데이트를 최적화합니다. 우리는 올해 초 Gatsby Cloud 배포의 엄청난 성능 향상을 비롯해 많은 개선사항을 제공했습니다.
RSG대 SSG를 벤치마크 하기 위해 Gatsby Cloud와 Netlify에서 정확히 동일한 Gatsby 사이트로 벤치마크를 수행했습니다.
다음 표에서 p는 백분율을 나타냅니다. p50은 실행의 50%가 해당 시간 내에 완료되었음을 의미합니다.
p50 | p75 | p99 | |
---|---|---|---|
Gatsby Cloud RSG | 1.3s | 1.7s | 4.1s |
Netlify Gatsby SSG | 124s | 132s | 152s |
결론: RSG는 CDN 캐시의 페이지를 업데이트할 때 SSG보다 약 100배 빠릅니다.
1999년, HTTP 1.1은 Cache-Control 헤더를 도입하여 사이트가 CDN의 에셋을 "maxAge"가 만료될 때까지 캐시 할 수 있게 했습니다.
일반적인 애플리케이션의 캐싱 기술은 아래와 비슷합니다.
const cache = new Cache()
// 비용이 큰 프로세스에 캐시를 사용합니다.
const maxAge_s = 60
If (cache.has(key)) {
return cache.get(key)
} else {
const output = generateOutput(key)
// maxAge_s 후 캐시 된 output을 만료시킵니다.
cache.set(key, output, maxAge_s)
return output
}
maxAge는 일반적으로 사이트에서 구현하기 매우 간단합니다. 각 에셋에 대해 Cache-Control 헤더를 설정해 항목을 새로 고치거나 재검증(revalidating)하기 전까지 캐시 할 기간을 CDN에 알려줍니다. Next.js의 ISR도 이 기술의 한 예입니다.
maxAge 값을 설정하는 데에는 미묘한 차이가 많습니다. 이에 대해서는 다음 글에서 자세히 다루겠습니다. 일단 maxAge가 30초로 설정되어 평균적으로 30초가 지난 후 재고량이 stale 된다고 가정하겠습니다.
p50 | p75 | p99 | |
---|---|---|---|
Gatsby Cloud RSG | 1.3s | 1.7s | 4.1s |
Remix/Fastly: maxAge | 30s | 30s | 30s |
결론: maxAge를 적용한 SSR은 페이지 업데이트가 SSG보다 약 4배 빠르고 RSG보다 약 20배 느립니다.
CDN 캐시를 업데이트하는 훨씬 더 성능 좋은 방법은 2014년 Fastly에서 도입되었습니다. 이는 두 가지 아이디어를 결합합니다. 첫 번째는 stale-while-revalidate입니다. 캐시를 즉시 무효화하는 대신 백그라운드의 CDN이 origin에 대해 에셋을 재검증합니다. origin이 업데이트를 반환하면 캐시를 업데이트합니다. 이는 때때로 느리거나 오류를 반환할 수 있는 백엔드 API로부터 보호하므로 매우 유용합니다. 캐시는 백엔드가 적절한 업데이트를 반환할 때까지 유효한 상태를 유지합니다.
stale-while-revalidate는 CDN 및 브라우저에서 정말 잘 지원되며 상당한 인기를 얻었습니다.
Fastly는 한 단계 더 나아가 백엔드가 maxAge 시간 초과를 기다리지 않고 경로를 즉시 재검증하도록 Fastly에게 지시할 수 있게 stale-while-revalidate를 purge API와 결합했습니다. 수동 재검증을 위한 이 기술은 여전히 지원하는 곳이 많지 않지만 지원하는 CDN이 늘어나고 있습니다.
이 CDN 기술은 아래 일반적인 앱 캐싱 기술과 유사합니다.
const cache = new Cache()
// 비용이 큰 프로세스에 캐시를 사용합니다.
If (cache.has(key)) {
return cache.get(key)
} else {
const output = generateOutput(key)
cache.set(key, output)
return output
}
// 데이터 업데이트를 수신하고 캐시를 업데이트합니다.
subscribeToDataChanges(key => {
const output = generateOutput(key)
cache.set(key, output)
})
저는 두 벤치마크 사이트에 이 기술을 구현했습니다. 하나는 Fastly CDN을 사용하는 Fly.io에서 실행 중인 Remix 사이트이고 다른 하나는 Vercel에서 실행되는 Next.js 사이트입니다.
두 사이트 모두에 다음과 같은 글루 코드(glue code)를 작성했습니다.
역주: 글루 코드(glue code)는 프로그램 요구사항 구현과는 관계 없이 호환성이 없는 부분을 결합하기 위해 동작하는 코드입니다.
이 기술은 반응형 사이트 생성과 유사합니다. RSG는 데이터 종속성 그래프를 작성하고 이를 바탕으로 실시간 데이터 변경 스트림에 대해 페이지를 무효화 시키는 시기를 결정하는 프로세스입니다. Gatsby는 이를 프레임워크에 적용했지만 다른 시스템에서도 동일한 아이디어를 구현할 수 있습니다.
Remix 사이트를 위한 Fastly에 이 패턴을 설정하기 위해 제품 경로를 통해 다음 문서 헤더를 반환하도록 했습니다.
{
"Cache-Control": "public, max-age=0, must-revalidate",
"Surrogate-Control": "max-age=60, stale-while-revalidate=200, stale-if-error=6000",
}
"Cache-Control"은 브라우저를 위한 헤더이고, "Surrogate-Control"은 origin(Remix)에서 에셋을 캐시 하는 방법을 Fastly에 지시합니다.
Next.js 사이트의 경우 이 기술을 구현하는 새로운 온디맨드(On-Demand) ISR 기능을 사용했습니다.
결과는 다음과 같습니다.
p50 | p75 | p99 | |
---|---|---|---|
Gatsby Cloud RSG | 1.3s | 1.7s | 4.1s |
Remix/Fastly: revalidate | 0.4s | 0.48s | 0.6s |
Next.js/Vercel: revalidate | 0.97s | 4.1s | 8.4s |
결론: SSR:SWR/재검증(Revalidation)은 SSG보다 약 120배, SSR:maxAge보다 30배 빠르며 RSG와 비슷합니다.
재고량이 변경된 후 이커머스 웹사이트에 오래된 데이터가 표시되는 시간을 측정하는 벤치마크를 다시 한번 수행했습니다.
모든 결과에 대한 표와 차트입니다.
p50 | p75 | p99 | |
---|---|---|---|
Gatsby Cloud RSG | 1.3s | 1.7s | 4.1s |
Netlify Gatsby SSG | 124s | 132s | 152s |
Remix/Fastly — maxAge | 30s | 30s | 30s |
Remix/Fastly — revalidate | 0.4s | 0.48s | 0.6s |
Next.js/Vercel — revalidate | 0.97s | 4.1s | 8.4s |
이는 일반적인 지식과 일치합니다. SSG는 빠르게 변화하는 데이터를 캐싱 하는데 적합하지 않습니다. SSR과 함께 maxAge를 사용하는 것은 SSG보다 빠르지만 그렇게 빠르진 않습니다. 그리고 가장 빠른 업데이트를 위해 Gatsby Cloud의 RSG이나 수동 재검증과 함께 SSR을 사용하면 CDN을 즉시 업데이트할 수 있습니다.
그럼 이 데이터가 RSG에 있어 어떤 의미를 갖는걸까요? Gatsby Cloud의 RSG 모델은 실시간 데이터 업데이트를 위한 SSR 캐싱 기술과 비견되거나 능가하고, SSG보다 훨씬 빠르다는 것입니다.
우리는 이를 위해 몇 년을 보냈고 우리가 성취한 것에 이보다 더 만족할 수 없습니다.
다음 글에서는 데이터 레이어와 데이터를 로컬로 동기화해 기존 SSG에 비해 매우 빠르게 재구축 하는 방법에 대해 깊이 살펴보겠습니다.
마지막 글에서는 미래에 대해 살펴보겠습니다. Gatsby의 데이터 레이어와 반응형 사이트 생성은 웹에서 구축할 수 있는 많은 새로운 가능성을 열어줍니다. 그중 몇 가지를 살펴보겠습니다.
저희의 목표는 Gatsby가 100,000페이지가 넘는 큰 사이트로 쉽게 확장할 수 있도록 하고 개발자에게 인터넷에서 최고의 웹사이트를 제공할 수 있는 능력과 유연성을 제공하는 것입니다.
7년간 Gatsby를 작업했음에도 불구하고 여러 면에서 저희가 이제 막 시작했다는 느낌이 듭니다. Gatsby는 2015년 최초의 React 메타 프레임워크로 시작해 가장 인기 있는 CMS, 서버리스 함수, SSG, SSR 및 지금의 RSG 지원과의 긴밀한 통합을 통해 강력하고 빠른 프레임워크로 발전했습니다. Gatsby를 한동안 사용하지 않았다면 훨씬 빨라진 속도에 기분 좋게 놀라실 수 있을 겁니다.
🚀 한국어로 된 프런트엔드 아티클을 빠르게 받아보고 싶다면 Korean FE Article(https://kofearticle.substack.com/)을 구독해주세요!