정적 콘텐츠의 Static Site Generation을 꺼보았다

정적 콘텐츠의 Static Site Generation을 꺼보았다

사례를 따라간 후 나의 힘으로 다시 되돌아가기

정확히 한달 전에 새로운 가이드를 배포했다. 기존 가이드는 젠데스크를 사용했는데, 콘텐츠의 양이 많아지는 것의 관리 문제, 커스텀 테마의 필요성, 정보 구조 체계화 등 다양한 이야기가 터져나오며 위험을 무릅쓰고 Headless CMS인 Contentful로 이사를 결정했다.

Airbridge Help Center

콘텐츠를 이사했으니 이를 제공할 페이지를 따로 만들어야 한다. 놀랍게도 지난 6년간 한 번도 서버 사이드 렌더링을 프로덕션에서 다룬 적이 없었기에, 이번 기회를 빌려 React 서버 컴포넌트 기반의 Next.js App Router를 써보기로 했다.

CMS 예시 프로젝트들 모두 getStaticProps() 또는 generateStaticParams() 를 사용해 페이지를 사전에 정적으로 렌더링하게 되어 있었다. ‘아 그런가보다’ 하고 로직을 작성했는데, 점점 옮겨지는 콘텐츠의 양이 급격하게 늘어나며 1분 정도 걸리던 빌드가 5~6분 넘게 걸릴 정도로 느려졌다. 정적 페이지인 ‘가이드’라고 하지만, 앞으로 기능을 추가하거나 콘텐츠의 구조를 변경할 일도 꽤 많았기에 느린 빌드 시간을 보며 심란해질 수밖에 없었다. 어떻게 해야할까?

개선을 위한 고민을 하다 우연히 아래의 영상을 보게 되었다. App Router가 Pages Router보다 느리지 않다는 점을 이야기하면서, 데이터 캐시를 사용하여 각 페이지 내에서 사용하는 네트워크 요청을 캐싱하고, 최초 접속 이후 다시 페이지에 들어갈 때 캐시를 사용하여 빠른 속도로 페이지를 표시했다.

조금 더 찾아보았더니, App Router 공식 문서에서 SSG, ISR 등을 모두 ‘Static and Dynamic Rendering’이라는 문서에 연결되게 해놓았고, SSG는 ‘Static Rendering’으로, ISR은 fetch의 revalidate나 cache 옵션을 사용한 ‘Static Data Fetching’으로 설명해놓았다.

이 내용을 읽고 ‘가이드’라는 서비스의 특성을 생각해봤다. 기본적으로 필요로 할 때 보며, 본다고 해도 SDK 설치 등 기본적인 페이지들이 대부분에 달한다. 그렇다면 모든 데이터를 미리 정적으로 렌더링할 필요가 있을까 생각이 들었다.

정적 렌더링 대신 데이터 캐시를 사용했을 때, 렌더링 속도의 효과를 보려면 적어도 한 번은 해당 페이지에 접속해야 한다. 그렇다면 모든 페이지를 한번은 열리게 하기 위한 방법을 고민했다. 그러다 Unlighthouse라는 도구가 sitemap.xml을 읽은 후 모든 페이지에 Lighthouse를 돌리는 것을 보고, 딱히 무언가를 하지 않아도 된다는 것을 알게 되었다.

Sitemap이 잘 되어있다면, Google Search Console 등 크롤러가 그것을 읽고 모든 페이지에 1회 이상 접속할 것이기 때문에 별도의 수고 없이 데이터 캐시의 이점을 얻을 수 있게 되기 때문이다. 그렇다면 revalidate 옵션을 길게 설정하거나 cache: 'force-cache' 를 주어도 괜찮다는 생각이 들었다.

한 번 테스트 환경을 만들어 실험을 해보았다. 먼저 generateStaticParams() 로 SSG를 생성하는 로직을 모두 삭제하고, fetch 옵션에 next.revalidate 를 1달 정도로 설정해 데이터 캐시가 적용되게끔 했다. (2,592,000s, 어차피 가이드의 모든 페이지가 자주 바뀌는 것은 아니다)

위의 작업을 적용했을 때, 빌드 속도는 기존 5~6분에서 1분 10초 대로 줄어들었다. Pagespeed Insights를 돌렸을 때에 성능에도 큰 영향이 없었다. 이 옵션을 프로덕션에 적용해도 되겠다고 판단이 들어 바로 적용을 했다.

PageSpeed Insights benchmark

이번에 몇년만에 처음으로 Next.js를 다뤄보면서, 그리고 React의 서버 컴포넌트를 비롯한 최신 내용들을 공부하고 적용하며 개발이 매우 즐거웠다.

생각해보니 즐거웠던 이유 중 하나가... 새로운 것을 배우기에 이전의 사례나 권장사항을 그대로 따라봤고, 프로덕션에 적용한 후 문제를 경험하여, 배운 것을 재점검하는 과정을 거치며 '왜 그렇게 안내하고 있을까?'를 생각해볼 수 있어서 그랬던 것 같다. 프로덕션의 기능을 만들다보면 이 지점을 놓치며 슬슬 재미가 없어지게 되는 것 같다. 얼마만의 순수한 재미였는가.

어쨌든, 이것 외에도 가이드를 만들며 하고 싶은 이야기가 굉장히 많다. 시간이 되는대로 종종 블로그에 남겨두어야겠다.