페이지 캐싱 첫번째 주제 = 풀 라우트 캐시
/a 라는 페이지의 렌더링 결과를 빌드타임에 미리 fetch 로 데이터도 불러오고, 데이터 캐싱도 해서, 결과적으로 사전렌더링을 완료하게되면, 렌더링 결과를 풀라우트 캐시라는 이름으로 페이지의 생성 결과를 서버측에 저장한다.
빌드타임이 끝난 이후에 실제 /a 로 접속요청이 들어오면, 앞서 빌드타임에 미리 풀라우트 캐시에다 다 저장을 해뒀기 때문에 새롭게 렌더링 할 필요가 없다. 그래서 캐시가 히트되어서 캐시된 페이지가 그대로 브라우저에게 전송이 된다.
=> 빠른 속도, Page router의 SSG와 비슷
풀 라우트 캐시 정리🌟
빌드타임에 정적으로 페이지를 미리 만들어 놓고 캐시에 보관한 다음,브라우저에 요청이 들어오면 캐시에 저장된 페이지를 그대로 응답해주는 페이지 캐싱 기능이다.
데이터 캐시가 YES이면 데이터를 다시 안불러와도되는거임
서치 결과 페이지처럼 값이 유동적으로 변해서 데이터가 변할 수 있는 페이지는 자동적으로 다이나믹 페이지이다. 다이나믹 페이지가 아니면 모두 Static Page이다(디폴트)
다이나믹 페이지는 결국 브라우저로부터 접속 요청이 들어왔을때마다 매번 새롭게 페이지를 사전렌더링 해야함. 하지만 데이터 캐싱과 리퀘스트 메모이제이션 등은 다 할 수 있음. 그저 풀 라우트 캐시만 못할뿐
static page는 빌드타임에 풀 라우트 캐시로 페이지가 캐싱되니까
빌드타임 이후 a페이지로 요청이 들어오면 풀 라우트 캐시에 있는 데이터를 바로 보내준다
풀 라우트 캐시도 Revalidate 설정 가능하다. Revalidate 조건이 만족되면 데이터 캐시와 풀라우트 캐시 함께 업데이트 된다.
3초 경과 후 우선 빠르게 페이지를 반환하기 위해 상한 ;; 페이지를 반환하고 그 후 데이터를 업데이트 한다. 그리고 풀 라우트 캐시도 업데이트함. 그 후 업데이트된 풀 라우트 캐시를 잘 반환하게 되는겨.
Next.js에 존재하는 모든 페이지는 Static Page와 Dynamic Page로 분류가 된다.
Static Page에만 풀 라우트 캐시, 즉 페이지 캐싱이 제공이 된다.
빌드 타임에 해당 페이지를 생성한 결과가 풀 라우트 캐시라는 이름으로 보관되고, 브라우저에 해당 페이지 접속 요청을 받으면 이 보관된 페이지 캐시가 즉각적으로 응답되어 빠른 속도로 페이지를 반환한다.
이러한 풀 라우트 캐시가 적용되는 STatic Page (정적 페이지)에서 revalidate가 설정된 data fetching을 사용하게 될 경우, 데이터(캐시)가 새롭게 갱신될때 페이지 캐시(풀라우트 캐시) 까지 함께 업데이트 되어서 페이지가 특정 시간을 주기로 계속 업데이트가 된다.
서치바는 서버에서 사전렌더링 되지않게, 오직 클라이언트에서만 렌더링되게하기위해 Suspense 태그 안에 감싸주자
Next 서버에서 사전렌더링 진행할 때 이 Suspense로 묶여있는 컴포넌트들은 미완성(Suspense) 상태로, 즉 곧바로 렌더링하지않는다.
묶여잇는 컴포넌트의 비동기 작업이 종료가 될때까지 미완성 상태이다.
위의 경우 서치바의 비동기 작업은 바로 useSearchParams() 함수이다. 즉, 클라이언트 사이드에서 쿼리스트링을 불러왔을때, 다시말하자면 브라우저에 해당 컴포넌트가 마운트가 되었을때 서치바 컴포넌트의 비동기 작업이 종료되는것이므로
서치바 컴포넌트는 Suspense 태그 안에 묶여있다면, 서버 측 사전 렌더링에서는 완전히 제외된다.
Static 페이지에서 풀 라우트 캐시가 적용되므로 한입북스 인덱스 페이지를 static 페이지로 만드려고한다. 인덱스 페이지에 포함하는 모든 컴포넌트와 함수를 체크해보려고한다.
static 페이지로 만드는 방법엔
기존 fetch 함수 인자를
{
cache: 'force-cache',
}
로 바꾼다.
그리고 fetch 함수에서 revalidate 옵션을 사용하는 경우 dynamic 페이지로 만드는것과 상관은 딱히 없어서 그대로 냅둬도 된다.
async function RecoBooks() {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_SERVER_URL}/book/random`,
{ next: { revalidate: 3 } } // static page
)
...
다시 npm run build 하면
/
인덱스 페이지가 스태틱으로 잘 되었다. 즉 풀 라우트 캐시가 적용됨!
풀 라우트 캐시에 저장되는 static 페이지라고 해도, 데이터 패칭에 revalidate 옵션이 붙어있으면, revalidate 타임에 따라 계속해서 업데이트가 잘 된다.
export default async function Page({
searchParams,
}: {
searchParams: Promise<{ q?: string }>
}) {
const { q } = await searchParams
const res = await fetch(
`${process.env.NEXT_PUBLIC_API_SERVER_URL}/book/search?q=${q}`,
{ cache: 'force-cache' }
)
서치 페이지는 인덱스 페이지와 다르게 query string 처럼 동적인 값에 의존을 하고 있기 때문에 Static page로 설정할 수 없다. 대신 데이터 캐시를 활용하는 쪽으로 최적화 해줄수 있다.
도서 상세 페이지 또한, 어떤 id값이 들어올지 모르기 때문에 기본적으로 다이나믹 페이지이다.
이러한 동적 경로를 갖는 다이나믹 페이지를 static 페이지로써, 빌드타임에 생성되도록 하려면,
generateStaticParams
함수를 이용하여 return 값에 어떠한 도서 데이터들이 빌드타임에 만들어져야 하는지 먼저 알려줘야한다.
export function generateStaticParams() {
return [{ id: '1' }, { id: '2' }, { id: '3' }] //문자열로
}
=> id가 1,2,3 인 도서 페이지를 미리 빌드타임에 생성함
빌드하면 book/1,2,3 이 빌드타임에 다 렌더링 완료가 되어서 서버측에 풀 라우트 캐시로써 잘 보관됨!
참고로 generateStaticParams으로 지정했던 id값이 아닌 4번페이지에 접속했을 때도 해당 페이지가 실시간으로 다이나믹하게 페이지가 생성되고 풀라우트캐시에 저장된다...
풀라우트 캐시에 보관된 페이지는 다음 요청에선 새롭게 생성되지않는다
주의 - 데이터 캐싱이 설정되지않은 데이터 패칭이 존재하는 페이지일지라도 해당 id 1,2,3인 페이지는 강제로 Static Page로 설정됨