NextJS Caching

박재현·2024년 6월 4일
1

NEXT.JS

목록 보기
8/17
post-thumbnail

NextJS caching 관련해서 기록해두기

Data나 Page를 NextJS의 도움을 받으면 원하던 원하지 않던간에 Cached상태로 만들수 있고 몇가지 방법이 있다.

unstable_cache

해당 함수는 next/cache로 부터 불러와서 사용가능한 함수이고 이전에 글에서 정리를 해두긴 했다.

해당 함수는 연산처리가 많은 특정한 함수 혹은 기능이나 아니면 데이터베이스 Query 같은걸 cahced 상태로 만들도록 도와주는 함수다.

따라서 server component에서 Prisma를 통해 DB를 직접 조회하고 데이터를 얻어온 결과값을 cached로 만들수 있다는 소리다.

사용하는 방법은 매우 간단한데 react-query와 비슷하다.

첫번째 함수 인자로 계산 or DB query를 하는 함수. 즉, data를 계산하거나 어디선가 갖고오는 함수를 인자로 넣어주면 된다.

또한 해당 함수는 반드시 반환값을 가지고 있어야 하고, 해당 반환값을 cached로 만들어 버린다.

그리도 2번째 함수 인자로 key와 같이 unique한 name을 list 형태로 넣어주면 된다.

따라서 cached된 data는 2번째 인자로 넘겨준 이름을 기반으로 값을 찾게 된다.

import { unstable_cache } from "next/cache";

const getCachedEntireProduct = unstable_cache(getEntireProduct, ["entire_products"])

async function getEntireProduct() {
	const products = await PrismaDB.product.findMany()
    return products;
}

how to refresh ?

unstable_cache 함수를 이용해서 우리가 원하는 값을 cached로 만들었다면 어떻게 update를 할 수 있을까?

일단 update가 되지 않는다면, 새로운 데이터 혹은 값이 있다고 한들 계속해서 이전값을 사용하게 될것이고 이는 의도와 다르게 동작하기 때문에 필요에 따라서 원하는 데이터를 cached했다면 update또한 필요에 따라서 가능해야 한다.

1. revalidatePath

첫번째 방법은 바로 "revalidatePath"를 사용하는 방법이다.

import { revalidatePath } from "next/cache";

revalidatePath("/home");

위와같이 코드를 작성하면 /home path의 모든 cached된 것들을 refresh 해준다. (unstable_cache를 이용해서 cacehd로 만든 데이터와 fetch GET request를 통해서 cached된것들 모두 포함)

따라서 특정 path의 cached들을 모두 update하려면 특정 event에 맞게 해당 함수를 적절히 사용하면 된다.

당장 생각나는건 예를 들어서 useEffect를 사용할수도 있을거같고, Server Action Function을 사용할수도 있을거 같다.


2. revalidate: time

두번째 방법은 revalidate time을 설정해주는 방법이다.

import { unstable_cache } from "next/cache";

const getCachedEntireProduct = unstable_cache(getEntireProduct, ["entire_products"], {
 revalidate: 60
});

일단 시간의 단위는 sec로 ms단위로 생각해서 1000을 곱해버리다간 곤란해질수 있으니 유의해야 한다.

revalidate time은 일종의 TH로 생각하면 되는데, unstable_cache의 첫번째 인자로 넘겨준 함수가 반환값을 반환함현 그때부터 time이 움직이기 시작한다.

중요한것은 매60초 마다 update가 된다고 생각하겠지만 그게 아니다.

매 60초마다 cached된 data가 update되는것이 아니라, latest update된 시점이 60초가 지나고나서 user가 unstable_cache 첫번째 함수 인자로 넘겨준 함수로부터 어떠한 데이터를 얻고자 할때 업데이트가 된다.

즉, 정리하면 위 코드의 경우 data를 cached로 만들고 60초가 지난 시점에서 user가 data좀 보자! 라고 요청을 했을때 update가 된다. 60초 마다 매번 자동으로 update되는것이 아니다!

그리고 추가적으로 당연하겠지만 latest update되고 60초 이내에 user가 data를 요청하면, nextjs는 "아직 data 싱싱함ㅋ 쌔거 꺼내올 필요 없음ㅋ" 이러면서 cachaed된 data를 넘겨준다.


3. revalidateTag

세번째 방법으로는 revalidateTag다.

사용방법은 첫번째 방법으로 작성한 revalidatePath와 크게 다르지 않다.

import { unstable_cache, revalidateTag } from "next/cache";

const getCachedEntireProduct = unstable_cache(getEntireProduct, ["entire_products"], {
 tags: ["products", "list", "sale"]
});

revalidateTag("sale");

일단 먼저 cached될 data들에게 tag를 부여해야 한다.

여기서 tag는 Instagram의 해시태그를 생각하면 편한데, unstable_cache의 두번째 인자로 넘겨준 name은 unique해야 하지만, tag는 unique할 필요가 없다.

왜냐면 인스타그램의 해시태그와 똑같은데, 여러가지 게시물에서 동일한 해시태그를 사용할수 있듯이 unstable_cached와 fetch모두 동일한 태그를 여러개 사용할 수 있다.

일단 위와 같이 "sale" 태그를 update하겠다고 하면, "sale" 태그를 가지고있는 모든 cached된 데이터들이 update된다.

이 부분은 revalidatePath와 약간의 차이가 있는데, revalidatePath는 해당 path에 연결되어 있는 모든 cached된 data들이 update된다.

하지만 revalidataTag를 사용하게 되면 1개의 path에 여러개의 cached된 데이터가 있다고 한들, 명시한 특정 tag를 가지고 있는 cached 데이터만 업데이트 된다.

따라서 보다 구체적이게 cacehd된 데이터를 update할 수 있다.


위에서 짧게 언급했지만 DB를 집적 조회하거나 아니면 어떤 값을 연산하거나 등등 "특정 data를 unstable_cache를 이용해서 cached"로 만들수 있지만, 우리의 nextjs는 fetch 또한 자동으로 cached 해준다. 아 물론 cookies, headers를 사용하지 않는 GET request에 한해서.

사실 fetch 함수를 통해서 API로 부터 값을 받아오는 일이 더 많을건데, 이때 GET Request는 자동으로 cached가 되고, 따라서 user가 해당 페이지를 다시 봐도 update가 자동으로 되지 않아서 난감한 경우가 나는 있었다.

관련해서 fetch를 통해서 cached된 data를 update 하는 방법에 대해서도 한번 정리해보자.

fetch

options.cache.no-store

먼저 fetch GET Request의 options중에 no-store를 사용하면 fetch를 사용함에도 불구하고 nextjs가 자동으로 cached하는 일을 막을 수 있다.

즉, 무조건 latest 상태의 data를 표시하고 싶을때라거나 아니면 user정보와 같이 민감한 정보들의 경우를 다룰때 사용할 수 있을거같다.


options.next.revalidate

위에서 unstable_cache 관련해서 정리했던 부분하고 매우 유사하다!

fetch("https://some-api", {
 next: {
  revalidate: 60
 }
})

일단 동작하는 방식은 unstable_cache의 revalidate와 동일하다.

60을 넣어줬다면, 60초가 지난 시점에서 해당 fetch request를 다시 수행한다는 소리가 되고 그렇지 않으면 cached된 데이터를 넘겨주게 된다.

여기서 중요한건 NextJS의 fetch함수에서만 저 기능이 동작한다는 거다.

그냥 일반 자바스크립트나, 다른 라이브러리를 사용해서 위와같이 fetch함수의 next: revalidate를 사용하면 정상적으로 동작하지 않을거같다.

일단 공식문서에서 아래와 같이 nextjs는 native web fetch를 확장했다고 적혀있다.
Next.js extends the native Web fetch() API to allow each request on the server to set its own persistent caching semantics.


options.next.tags

이 부분도 unstable_cached를 다룰때 설명했던 revalidateTag를 사용하는 방법이다.

fetch("https://some-api", {
 next: {
  tags: ["products"]
 }
})

revalidateTag("products");

위와같이 간단하게 사용할수 있고, 만약에 unstable_cache와 fetch 함수에서 모두 products라는 tag를 부여한 상태에서 revalidateTag("products") 라고 한한다면 unstable_cache + fetch 함수의 cached data가 모두 update하게 될거다.


추가적으로!

fetch("https://some-api");

revaliatePath("/home");

위와 같이 코드를 작성했다고 가정하면, fetch함수는 알아서 자동으로 GET request의 response를 cached로 만들거고 url path가 home으로 이동하게되면 해당 path에 dependecny가 있는 fetch함수도 자동으로 update가 된다.

profile
기술만 좋은 S급이 아니라, 태도가 좋은 A급이 되자

0개의 댓글

관련 채용 정보