사건의 발단
상사 : 제품 소개 페이지들을 만들자.
나 : 속으로 생각 중 ( 제품 소개 페이지들은 변경될 일이 거의 없으니까 SSG로 만들까? 근데 만약에 관리자 페이지에서 해당 제품 정보를 변경하면 어떡하지…? SSG는 프로젝트를 빌드한 시점에 페이지를 생성해서 변경되지 않잖아…)
나 : ISR로 캐싱시간을 10분? 1시간? 하루?를 줘서 페이지를 업데이트해주는 건 어떻게 생각하세요?
상사 : 만약에 그 10분, 1시간, 하루 사이에 중요한 정보가 바뀐다면 어떡할래? 책임질 수 있어?
나 : 어…그럼 사용자도 거의 없으니까… 그냥 요청마다… SSR하시죠… 캐싱하지 말죠… 하하하
(친구와 한풀이를 하며,,,)
나 : 오늘 이런 일이 있었다,,,
친구 : 어 그거 ISR on demand revalidation라고 검색해 봐
간단 단어 정리
SSG : 빌드 시점에 페이지를 생성해서 서버에서 갖고 있음.
SSR : 매요청마다 서버에서 페이지를 항상 렌더링 해서 사용자에게 제공함.
ISR : 특정 주기, 트리거에 의해서 서버에서 페이지를 렌더링해서 사용자에게 제공함.
주문형 재검증(On-Demand Revalidation)이란?
필요한 때에만 요청에 따라서 캐싱되어 있던 data를 최신의 상태로 변경할 수 있습니다.
그로 인해 사용자는 최신의 정보를 받을 수 있어서 사용자 경험 향상과 캐싱을 통해 서버의 부담 저하를 할 수 있습니다.
지금 우리는 AWS S3에 HTML을 올려둔 게 아니라 NextJS라는 서버에 HTML을 만들어놓은 거라서 업데이트를 할 수 있습니다.
즉, next.js의 SSG(static site generator)로 프로젝트 빌드 시에 생성된 웹 페이지의 경우 next.js 자체를 다시 빌드하지 않으면 해당 페이지가 업데이트되지 않지만, next.js는 서버로 동작하기 때문에 주문형 재검증을 사용하여 정적으로 만든 페이지를 다시 빌드하여 사용자에게 최신의 data를 지닌 페이지를 제공할 수 있습니다.
적용 원칙
- 사용자가 많이 이용하는 페이지.
- 자주 변경되지는 않지만 변경될 가능성이 있는 페이지.
이에 해당하는 페이지인 콘텐츠, 공지사항 페이지에만 적용하기로 함.
그러나, 전제는 서버의 성능을 위함이지만, 사용자들의 유입 정도와 코드의 유지보수 측면을 고려하여 적용해 주는 것이 좋을 것 같습니다.
revalidateTag
- tag를 지정해서 해당 태그를 사용하여 Next.js의 api를 호출하여 알릴 수 있습니다.
1. SSG로 페이지 만들기
// src/app/content/[contentId]/page.tsx
export default async function page(params) {
const res = await fetch('https://...', { cache: 'force-cache', next: { tags: [params.contentId] } })
const data = await res.json()
// ...
}
2. Next.js API Routes를 사용하여 API 만들기
- API Routes는 간단히 설명하자면, next.js의 특정 페이지 경로에 HTTP 요청을 보낼 수 있는 것입니다. (그냥 백엔드 API 구현하는 거랑 같다고 생각하시면 됩니다)
- 백엔드가 Next.js가 나눠져 있기 때문에 백엔드 서버에서 Next.js API를 호출해줘야 해서 API Routes를 생성하였습니다.
- 백엔드도 Next.js에서 구현했다면 이 api는 만들 필요가 없었음.
- POST “도메인/api/rebuild"에 body에 {rebuildUrl : 바꿀 TAG}를 실어서 요청하면 됨.
// src/app/api/rebuild/route.ts
import { revalidateTag } from 'next/cache';
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
const { rebuildUrl } = await request.json();
revalidateTag(rebuildUrl);
return NextResponse.json({ revalidated: true, now: Date.now() });
}
도중에 만난 이슈
- body 값 이상함. 원인 : request 변수에 await 안 해서 그럼
- 로컬에서 테스트 시 빌드된 페이지가 캐싱되어 있음.
- SSG로 해당 페이지 빌드생성 했음. (페이지 제목 : 김치)
- 해당 페이지의 data를 서버에서 변경함 (페이지 제목 : 김치찌개)
- next.js에서 빌드 다시 함 (npm run build)
- 해당 페이지는 변경 전 상태인 (페이지 제목 : 김치)인 상태
- Nextjs revalidatePath not working
- 관련 이슈 : https://github.com/vercel/next.js/issues/49387
- 처음에는 revalidatePath 메서드를 사용하여 구현하였는데 재빌드 되지 않았다,,, 찾아보니 동적경로를 재빌드가 잘되지 않는다는 버그가 발견되었고 2023년에 생긴 이슈가 아직 해결되지 않아서… revalidateTag로 변경하였음.
- POST인가 GET인가
- RESTful API를 하려면 멱등성을 지켜야 하기 때문에 POST 요청은 DB의 data가 바뀌거나 하는 거고 GET은 DB가 바뀌지 않고 조회만 해야 RESTFul 한 것이라 판단하였고 또한 GET을 사용하여 query string으로 요청하는 경우에는 data의 길이가 길어지는 것도 고심해야 해서 POST로 API를 생성하였다.
- 지금은 페이지를 리빌드를 해야 해서 변경이니깐 POST가 맞다는 의견!
Reference
https://nextjs.org/docs/app/building-your-application/routing
'Frontend' 카테고리의 다른 글
styled-component로 GlobalStyle 정의하기 (0) | 2023.04.04 |
---|---|
디바운싱과 쓰로틀링 (0) | 2022.11.26 |
Next.js 쓰면 SSR 하고 있는거 아님? (2) | 2022.11.18 |
프론트엔드 면접 경험 (0) | 2022.11.16 |
[JS] this란? (0) | 2022.08.23 |