Next.js in general

김명성·2022년 4월 23일
1

Next.js

목록 보기
4/7

Next.js In General


🟢 가능한 캐싱을 사용하자.

Use caching wherever possible.


Next.js는 /_next_/static Javascript CSS Static iamge와 같은
Static assets에 caching headers를 자동으로 추가해주는 방식으로 응답 시간을 개선시키고 외부서비스에 대한 요청의 수를 줄여준다.

Cache-Control: public, max-age=31536000, immutable

next.config.js내에 설정된 Cache-Control header는 Static assets을 효과적으로 캐싱할 수 있도록 프로덕션에서 설정된 헤더를 덮어 쓴다.

정적으로 생성된 페이지(SSG)의 cache에 대해 재검증(revalidate)이 필요한 경우, 페이지의 getStaticProps function 내부에서 revalidate 속성을 통해 재검증이 가능하게 설정하면 된다.

만약 페이지 내에서 next/image를 사용중이라면, default image Optimization loader 에 명시된 caching rules를 따른다.

Cache-Control: no-cache, no-store, max-age=0, must-revalidate
local 환경에서 next dev를 통해 실행중이라면, local에서 caching하는 것을 방지하기 위해 header를 overwrite한다.

또한 dynamic responses(SSR)를 위해 getServerSideProps 및 API 경로 내에서 캐싱 헤더를 사용할 수도 있다.
예를 들어 stale-while-revalidate를 사용한다.

export async function getServerSideProps({ req, res }) {
  res.setHeader(
    'Cache-Control',
    'public, s-maxage=10, stale-while-revalidate=59'
  )

  return {
    props: {},
  }
}

s-maxage:number 새로운 요청으로 간주되는 시간(초)
stale-while-revalidate:number 케시된 값은 stale 상태가 되지만 랜더링 되게 한다.

기본적으로 Cache-Control은 페이지에서 데이터를 가져오는 방법에 따라 다르게 설정된다.

페이지가 getServerSideProps를 사용하는 경우
다른 캐시 동작을 하기 원하면 위와 같이 getServerSide Props 함수 내부에서 res.setHeader('Cache-Control','value_prefer')를 사용한다.

페이지가 getServerSideProps 또는 getInitialProps를 사용하는 경우
caching할 수 없는 response를 방지하기 위해 기본 Cache-Control헤더를 사용한다.

페이지가 getStaticProps를 사용하면서 revalidate를 사용하지 않는 경우 caching이 오래 지속될 수 있게
s-maxage = 31536000,stale-while-revalidate를 가능한 최대 max로 끌어올려 사용한다.

stale-while-revalidate : second로 준 시간 이전의 반복 요청에 대해서는 캐싱된 값을 사용하고 그 이후에는 서버에 요청한다.
stale-while-revalidate가 Cache-Control의 확장기능이라고 생각하면 된다.
Example

Cache-Control: s-maxage=600, stale-while-revalidate=600

위 예제를 해석하면 Cache-Control max-age를 통해 10분
(s-maxage의 값 600seconds) 동안 응답 값이 fresh 상태이다.
fresh 상태일 때는 최신의 상태를 의미하기 때문에 새로운 http 요청이 발생해도 캐싱된 데이터를 반환한다.
10분 이후로는 stale-while-revalidate로 10분을 줬기 때문에 max-age로 준 10분이 지났을 때 응답 값이 더이상 fresh 상태가 아니고 stale상태지만 새로 요청을 보내지 않고 캐싱되어 있는 값을 반환한다.
하지만 이때 재검증 요청이 진행되고 새로 가져온 데이터가 이전에 캐시된 데이터와 동일하지 않으면 캐시를 갱신한다. 마지막으로 max-age 10분과 stale-while-revalidate 의 10분, 20분보다 오래된 값이라면 서버에 새로 요청을 보낸다.

배포할 때에는 dynamic responses에 대한 caching을 지원해야 한다.
자체 호스팅하는 경우 Redis와 같이 key/value store를 사용하여 추가하는 작업이 필요하다.

만약 Vercel을 통해 배포하였다면 Edge Caching은 구성 없이 작동한다.

Radis (Remote Dictionary Server)
원격 저장소 서버의 약자로서 key-value 구조의 비정형 데이터를 저장하고 관리하기 위한 오픈 소스 기반의 비관계형 데이터베이스 관리 시스템이다.

Edge Caching
캐싱은 오랫동안 사용자가 빠르게 검색할 수 있도록 임시데이터나 파일을 저장하는 메카니즘이었다.
Edge Caching은 기존 캐싱 방법과 매커니즘을 Edge Computing infra에 통합하는 것이다.
Edge Caching은 메모리 스토리지를 최종 사용자에게 더 가깝게 이동함으로써 광범위한 네트워크에 대한 스트레스를 줄이고, 콘텐츠 전달을 개선한다.
Edge Cache는 웹 개체, 비디오 및 소프트웨어 업데이트를 포함한 인터넷 기반 콘텐츠의 단면 캐싱을 가능하게 한다.
인터넷이나 WAN 링크를 통해 웹 개체를 다운로드하면, Edge Cache가 네트워크 가장자리에 해당 개체를 저장한다.
동일한 자료에 대한 후속 요청이 오면 WAN을 통해 데이터를 다시 다운로드할 필요 없이 콘텐츠가 Edge Cache에서 빠르게 전달한다.
그 결과 WAN 개체의 LAN 속도가 개선되고 사용자에게 더 나음 경험을 제공할 수 있다.
또한 Edge Cache는 HTTPS 사이트를 지원하므로 어플라이언스가 정방향 프록시가 되고 캐싱을 위해 콘텐츠를 해독할 수 있게 된다.


🟣 자바스크립트의 사이즈를 줄이자.

Aim to ship the least amount of JavaScript possible.

Defer loading heavy JavaScript bundles until needed.


브라우저로 보내는 자바스크립트의 양을 줄이기 위해
몇가지 툴을 사용해야 하는데, 먼저 Javascript 번들에 포함된 내용을 이해할 수 있어야 한다.

  • Import Cost - VSCode 내에서 가져온 패키지의 크기를 표시한다.

  • Package Phobia - 프로젝트 내 새로운 개발 종속성을 추가하는 비용을 찾는다.

  • Bundle Phobia - 종속성이 번들 크기를 얼마만큼 늘릴 수 있는지 분석한다.
    bundlephobia.com

  • Webpack Bundle Analyzer - webpack의 구성요소를 시각화한 트리맵을 확인한다. webpack bundle analyzer 설치

pages/ 폴더는 다음 빌드가 진행되는 동안 자동으로 자체 Javascript 번들로 code spliting된다.

또한 Dynamic Imports를 사용하여 lazy-load Components와 라이브러리들을 사용할 수 있다
예를 들면, 모달 코드가 사용자에게 오픈버튼이 클릭되기 전까지 defer loading(로드 지연) 되는 것을 원한다면 모달 코드를 가져오는 것을 연기할 수 있다.


🟣 logging이 설정되었는지 확인한다.

Ensure logging is set up.


Next.js는 클라이언트,서버 양쪽에서 실행되기 때문에 지원되는 여러가지 형태의 Logging이 있다.
브라우저의 console.log 와 서버에서의 stdout이 대표적인 예시다.

Pino 또는 Vercel을 사용하는 경우 Next.js와 호환되는 빌트인 로깅통합이 존재한다.


🟣 애러 처리가 설정되었는지 확인한다.

Ensure error handling is set up.

Configure the 404 (Not Found) and 500 (Error) pages.


제어할 수 없는 예외사항이 발생하였을 때, User-Experience를 위해 404, 500 page를 설정하자.
기본 Next.js의 테마 대신에 자신의 브랜드에 맞게 페이지를 설정하는 것이 좋을 것이다.

또한 Sentry와 같은 도구를 사용하여 Exception을 기록하고 추적할 수도 있다.
Next.js용 Sentry SDK를 사용하여 클라이언트,서버측에서 발생하는 오류를 잡는 예시가 있다.
https://github.com/vercel/next.js/tree/canary/examples/with-sentry

Vercel용 Sentry 통합버전도 있다.
https://vercel.com/integrations/sentry


🟣 로딩 성능을 향상시키자.

Ensure you are measuring performance.

Review Supported Browsers and Features.


Lighthouse를 실행하여 성능, 모범 사례, 접근성 및 SEO를 확인한다.
최상의 결과를 얻기 위해서는 Next.js의 production build를 사용하고,
브라우저의 Secret 모드를 통해 확장 프로그램의 영향을 받지 않게한다.

로딩 성능을 측정할 수 있게 되면 반복적으로 개선하면서 크게 성능이 개선되지 않을때까지 계속 조정한다.

이후 데이터베이스 또는 API가 배포된 곳과 가까운 곳에 caching regions를 사용한다.

또한 벡엔드에 과부화가 되지 않을만큼의 stale-while-revalidate 값을 사용하는 것도 중요하다.

Incremental Static Regeneration을 사용하여 백엔드로 요청하는 횟수를 줄인다.

사용하지 않는 자바스크립트를 제거한다.

핵심 성능 향상 지표에 번들 크기가 미치는 영향과 이를 줄이기 위해 사용할 수 있는 전략을 이해해야 한다.

import 비용과 크기를 보기 위해 코드 편집기를 설정한다.

사용하는 packages를 대체할 수 있는 더 작은 소형의 패키지를 찾아본다.

동적으로 로딩되는 컴포넌트들과 종속성을 갖는 컴포넌트 확인.


0개의 댓글