Next.js SSG & Prisma Acclerate
Prisma Acclerate 간단 설명
Django Cache API, Redis Cache와 같이 Node 백엔드 측에서 Prisma ORM을 사용할 때 적용할 수 있는 데이터 베이스 캐시를 이용한 가속화 기능이다.
Time-to-live TTL을 사용한 캐시 전략
오래된 캐시 데이터가 허용되는 경우 TTL을 사용하여 데이터베이스 로드를 줄이는 게 가능해진다.
Stale-while-revalidate SWR을 이용한 캐시 전략
SWR을 사용하면 최소한의 오래된 데이터로 요청에 빠르게 응답할 수 있다. 데이터베이스 로드를 줄이지는 않지만 응답 시간을 크게 향상할 수 있다.
TTL은 데이터 변화가 거의 없는 DetailView에 적용하기 적합하다.
SWR은 데이터가 주로 동적으로 변경되면서 자주 업데이트되는 ProfileView에 적용하기 적합하다.
Next.js SSG 간단 설명
- Next.js의 SSG는 해당 페이지를 정적으로 생성해 관리한다. 이는 웹 브라우저 캐시를 사용한다.
- 캐시 된 데이터가 유효하지 않을 경우 백그라운드에서 새로운 데이터를 가져와서 다시 캐시를 업데이트한다.
Stale-while-revalidate 전략이 기본 설정이며 두 가지 설정법이 있다.
- On-demand revalidation 캐시 전략을 제공한다. 데이터가 변경되는 서버 액션을 수행할 때 수동으로 캐시를 업데이트하는 방법이다. 예를 들어 블로그 포스팅을 수정을 했을 때 캐시를 즉시 업데이트 한다.
- Time-based Revalidation 캐시 전략을 제공한다. 주기적으로 유효기간을 정하고 업데이트하는 방법이다. 예를 들어 상품 페이지에 상품 이미지를 변경했을 때 수정 사항이 즉시 반영되는 게 아니라 설정한 간격마다 캐시를 업데이트한다.
요청에 따른 캐시 상태값
웹 브라우저와 데이터베이스에서 사용하는 캐시 상태의 명칭은 다를 수 있다. 이 포스팅에선 웹 브라우저의 캐시를 기준으로 몇 가지 설명한다.
- HIT 상태는 브라우저가 웹 서버에서 데이터를 가져오지 않고 캐시에서 데이터를 사용할 수 있는 경우를 의미한다.
- STALE 상태는 브라우저가 캐시에서 데이터를 사용하지만 캐시 된 데이터가 유효하지 않은 경우를 의미한다.
- MISS 상태는 브라우저가 캐시에서 데이터를 사용할 수 없고 웹 서버에서 데이터를 가져와야 하는 경우를 의미한다.
- UPDATING 상태는 웹 브라우저가 캐시 된 리소스를 업데이트하는 중임을 나타낸다.
TTL은 HIT, MISS 두 가지의 상태만을 사용한다.
Next.js 와 데이터베이스 캐시 동시 사용이유
Next.js 에서는 SSG를 제공하기 때문에 상세 페이지에 대해서 굳이 데이터베이스 TTL을 설정할 필요는 없다.
다만 사용자 프로필 페이지처럼 주로 동적으로 변경되고 액세스가 많이 일어나는 페이지가 있다면 어떨까?
동적이기 때문에 SSG를 적용하긴 어렵고 그렇다고 최적화를 진행하지 않으면 트래픽이 효율적이지 못할 거다.
GitHub TTL 예시
프로필의 이름과 이미지를 변경했으니 이름과 프로필 이미지가 즉시 반영되는 걸 기대한다.
결과는? 이름은 즉시 변경되었지만 이미지는 즉시 변경되지 않았다.
네트워크 탭을 통해서 확인해 보니 캐시의 유효기간이 5분으로 설정돼 있는 걸 확인할 수 있다.
여기서 유효기간 만료직전 프로필 이미지를 변경하였고 캐시가 새로 고쳐지는데 3분이 걸린다고 가정을 한번 해보고 시뮬레이션을 해본다.
유효기간 만료 전 (0~4분)
- A~D 사용자가 액세스하면 모두 캐시 HIT, 이전 프로필 이미지 표시
5분 경과 후
- E 사용자가 액세스하면 캐시 MISS, 이전 프로필 이미지 표시
- 백그라운드에서 새 프로필 이미지 캐싱 시작 (3분 소요)
6분 경과 후
- F 사용자가 액세스하면 캐시 MISS, 새 프로필 이미지 표시
- 캐시 업데이트 중
7분 경과 후
- G 사용자가 액세스하면 캐시 MISS, 새 프로필 이미지 표시
- 캐시 업데이트 중
8분 경과 후
- H 사용자가 액세스하면 캐시 HIT, 새 프로필 이미지 표시
- 캐싱 완료되어 새 이미지로 캐시 업데이트 후 TTL 타이머 리셋
요약:
- (0-4분) 유효기간 내 이전 이미지 캐시 HIT
(5-8분) 이전/새 이미지 MISS, 캐시 업데이트 중 - 8분 이후 새 이미지 캐시 HIT
이미지에 캐시를 적용하여 캐시의 유효기간이 끝나고 후속 요청이 있을 시에 캐시를 새로 고쳐 쓰는 것을 확인 가능하다.
즉, 데이터가 업데이트되었음에도 캐시의 동작 방식에 따라 어떠한 사용자는 최신 정보를 볼 수 있지만 다른 사용자는 만료된 캐시 정보를 보게 되어 최신 정보를 볼 수 없는 상황이 발생한다.
사용자 경험 개선을 위해서 이 부분에서는 Prisma Acclerate 이용하여 TTL + SWR을 동시에 사용할 수도 있다.
캐시가 존재할 시 30초 동안은 TTL 캐시가 히트하고 100초 동안은 이전 캐시 데이터를 보여준다. 130초에 사용자가 액세스 했을 시 새로운 캐시 데이터를 보여주게 된다. 이는 실제 데이터가 업데이트되었어도 만료된 캐시 된 데이터를 보게 되는 경우를 배제할 수 있다.
이 부분은 이후에 새로 Next.js 프로젝트를 생성하고 캐시 전략을 적용하여 이후 업로드될 포스팅에서 다룰예정이다.
이렇듯 프로덕션 환경에선 캐시를 이용해서 트래픽을 최적화하는 전략이 요구된다.
캐시는 무분별하게 사용되어서는 안 되며 데이터 베이스 쿼리 동작이나 API 요청에 캐시를 적용하는 방식은 복잡하고 까다로운 과정이라 연습이 많이 필요하다.
현재는 Node를 백엔드 서버로 두는 게 아닌 Django를 백엔드 서버로 두고 캐시를 사용하고 적용하는 과정을 계속 연습할 예정이다.