개요
꽤 오래전 글에서 Next Cache Key를 구하는 알고리즘을 분석하고 실제로 동일하게 만들어보기까지 하면서 RSC paylaod
를 관리해 볼 생각이었습니다. 이와 관련해 npm 라이브러리도 만들어보면서 큰 기대를 만들고 적용해 보려 했지만...
막상 만들고 적용해보니 쓸모가 없어졌는데, CMS에서 key를 생성해야 하는데 키 생성에 필요한 값들은 대부분 클라이언트에서 사용된다는 점, config 값을 사용해야 하는 점 등 생각보다 사용하는데 너무 많은 공수가 들어 잠시 접어뒀습니다.
그래서 이번 글에서는, Cache Key를 구하는 쪽에서 원하는 대로 set하는 쪽으로 방향을 틀어 제어한 방법을 공유해 보려 합니다.
왜 Cache Key 구하는 것에 집착을 했는지?
다음은 NextJS가 제공하는 custom cache handler 예제입니다.
캐시 흐름에 대해 보면, 요청이 들어올 때 get 메서드에서 key가 있다면 Cache HIT
, 없다면 Cache MISS
로 set 메서드를 통해 새 캐시를 저장합니다.
여기서 set 메서드에서 key를 커스텀 해서 저장한다면, get에서 key를 받아올 수가 없습니다. 이 key는 NextJS 내부에서 만들어지기 때문이죠. 따라서 제가 이 key를 구할 수만 있다면, 캐시에 접근해 관리를 해볼 생각이었습니다.
이 방법은 개요에서 소개한 것처럼, 더 효율적인 방법을 찾기 위해 잠시 중단했습니다.
두 번째 파라미터 ctx를 이용하자
문서엔 없지만, 구현체를 보면 get 메서드는 두 번째 파라미터 ctx를 제공합니다.
ctx 안에는 무엇이 있을까요? incremetal-cache
파일 안에서 확인해 볼 수 있습니다.
익숙한 옵션들이 많이 보이는데, 특히 눈에 띄는 건 tags입니다. 예제의 set 메서드에서 사용했죠. 예제에서 payload의 value는 { value, lastModified, tags }
로 구성되어 있습니다.
tags는 무엇일까요? 예상했던 것처럼 On Demand 방식을 위한 Revalidate Tag의 tag입니다. 이제 get, set 메서드 간에 내부에서 생성되는 key 말고도 우리가 설정할 수 있는 tag를 공유할 수 있게 된 겁니다.
tags를 이용한 key 커스텀하기
next option을 이용해 다음과 같이 요청을 해보겠습니다.
이제 세팅한 tags를 이용해 동일하게 customKey
를 만듭니다.
최종 저장된 값은 다음과 같습니다.
tags를 사용하지 않는 경우 리팩토링
tags를 설정하지 않는 요청이 더 많을 거라고 예상됩니다. 이 경우 key가 존재하지 않기 때문에, 캐시를 할 수 없습니다.
tags가 없는 경우는 그대로 NextJS의 key를 사용할 수 있게 리팩토링합니다. tags가 없다면 기존처럼 내부 캐시 파이프라인을 수행할 수 있게 하는 것이죠.
revalidate 과정을 없애자
NextJS가 알아서 해주는데 굳이 Cache를 핸들링 하려는 이유가 무엇일까요. CMS를 통해 외부에서 데이터를 관리한다면, On Demand로 revalidate 하기 굉장히 번거롭습니다.
- CMS에서 데이터 업데이트 시 Next 서비스로 queryString에 업데이트하고자 하는 tags를 포함해 요청하기
- 서비스에선 route handler를 이용해 CMS의 요청으로부터 queryString을 파싱, tags 추출
- revalidateTag 실행
보기엔 간결해 보이지만, 이 과정에서 CMS와 서비스 간의 CORS 설정이나, 무분별한 route handler 호출을 막기 위한 header 설정 등 굉장히 많은 공수가 들어가게 됩니다. 예외 처리해야 하는 코드 또한 늘어납니다.
반면 캐시를 커스텀 하면 어떻게 될까요. 단지 CMS에서 데이터 업데이트 시 저장소에 접근, customKey를 통해 Cache를 Purge 시키면 그만입니다. 그렇다면 자동으로 NextJS는 Cache MISS, DB에 접근해 새 데이터를 받아올 수 있는 것이죠. (다만 서비스와 CMS 간에 tags 관리는 더 연구가 필요해 보입니다.)
Sever Action을 이용하면 위의 과정을 거치진 않지만, 이 경우에도 즉시 Cache Purge를 통해 NextJS의 revalidate 실행하는 과정을 생략할 수 있습니다.
마무리
아직 POC 단계이지만 꾸준히 관심을 가지고 개선한 결과, 회사가 겪고 있는 기술적 챌린지를 하나씩 해결해 나간다는 점에서 큰 보람을 느낍니다.
사실 NextJS가 제공하는 가이드대로만 해도 문제를 해결할 수 있지만, 더 나은 방향으로 개선하기 위해 앞으로도 계속 다듬어 나가려고 합니다.