정적 렌더링은 페이지가 헤드리스 CMS에서 데이터를 가져올 때 유용하다. 그러나 헤드리스 CMS에서 초안을 작성할 때 페이지에서 즉시 초안을 보고 싶을 때는 적합하지 않다. Next.js가 빌드 시간 대신 요청 시간에 이러한 페이지를 렌더링 하고 게시된 콘텐츠 대신 초안 콘텐츠를 가져오길 원할 것이다. 이 특정한 경우에만 Next.js가 동적 렌더링으로 전환되기를 원할 것이다.
Next.js에는 이 문제를 해결하는 Draft Mode라는 기능이 있다. 다음은 사용 방법에 대한 지침이다.
- Step 1: Route Handler 생성 및 액세스
먼저 경로 처리기를 만든다. 어떤 이름이든 가질 수 있다. app/api/draft/route.ts 그런 다음 next/headers에서 draftMode를 가져오고 enable() 메서드를 호출한다.
// app/api/draft/route.ts
// route handler enabling draft mode
import { draftMode } from 'next/headers'
export async function GET(request: Request) {
draftMode().enable()
return new Response('Draft mode is enabled')
}
이렇게 하면 초안 모드를 활성화하는 쿠키가 설정된다. 이 쿠키를 포함하는 후속 요청은 정적으로 생성된 페이지의 동작을 변경하는 초안 모드를 트리거한다.
/api/draft를 방문하고 브라우저의 개발자 도구를 확인하여 이를 수동으로 테스트할 수 있다. 이름이 __prerender_bypass인 쿠키가 있는 Set-Cookie 응답 헤더를 확인하면 된다.
Headless CMS에서 안전하게 액세스
실제로는 헤드리스 CMS에서 안전하게 이 Route Handler를 호출하기를 원할 것이다. 구체적인 단계는 사용 중인 헤드리스 CMS에 따라 다르지만 다음은 수행할 수 있는 몇 가지 일반적인 단계이다.
이 단계에서는 사용 중인 헤드리스 CMS가 사용자 정의 초안 URL 설정을 지원한다고 가정한다. 그렇지 않은 경우에도 이 방법을 사용하여 초안 URL을 보호할 수 있지만 초안 URL을 수동으로 구성하고 액세스해야 한다.
먼저 선택한 토큰 생성기를 사용하여 비밀 토큰 문자열을 생성해야 한다. 이 비밀은 Next.js 앱과 헤드리스 CMS에서만 알 수 있다. 이 비밀은 CMS에 대한 액세스 권한이 없는 사람들이 초안 URL에 액세스 하는 것을 방지한다.
둘째, 헤드리스 CMS가 사용자 정의 초안 URL 설정을 지원하는 경우 다음을 초안 URL로 지정한다. 이는 Route Handler가 app/api/draft/route.ts에 있다고 가정한다.
https://<your-site>/api/draft?secret=<token>&slug=<path>
- <your-site>는 배포 도메인이어야 한다.
- <token>은 생성한 비밀 토큰으로 바꿔야 한다.
- <path>는 보려는 페이지의 경로여야 한다. /posts/foo를 보려면 &slug=/posts/foo를 사용해야 한다.
헤드리스 CMS를 사용하면 초안 URL에 변수를 포함할 수 있으므로 <path>가 다음과 같이 CMS의 데이터를 기반으로 동적으로 설정될 수 있다. &slug=/posts/{entry.fields.slug}
마지막으로 경로 처리기에서 먼저 secret이 일치하고 slug 매개변수가 존재하는지 확인한다(그렇지 않으면 요청이 실패해야 함). 둘째로 draftMode.enable()을 호출하여 쿠키를 설정한다. 그런 다음 slug에서 지정한 경로로 브라우저를 리디렉션 한다.
// app/api/draft/route.ts
// route handler with secret and slug
import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'
export async function GET(request: Request) {
// Parse query string parameters
const { searchParams } = new URL(request.url)
const secret = searchParams.get('secret')
const slug = searchParams.get('slug')
// Check the secret and next parameters
// This secret should only be known to this route handler and the CMS
if (secret !== 'MY_SECRET_TOKEN' || !slug) {
return new Response('Invalid token', { status: 401 })
}
// Fetch the headless CMS to check if the provided `slug` exists
// getPostBySlug would implement the required fetching logic to the headless CMS
const post = await getPostBySlug(slug)
// If the slug doesn't exist prevent draft mode from being enabled
if (!post) {
return new Response('Invalid slug', { status: 401 })
}
// Enable Draft Mode by setting the cookie
draftMode().enable()
// Redirect to the path from the fetched post
// We don't redirect to search Params.slug as that might lead to pen redirect vulnerablilries
redirect(post.slug)
}
성공하면 브라우저는 초안 모드 쿠키로 보려는 경로로 리디렉션 된다.
- Step 2: 페이지 업데이트
다음 단계는 페이지를 업데이트하여 draftMode().isEnabled 값을 확인하는 것이다. 쿠키가 설정된 페이지를 요청하면 빌드 시간이 아닌 요청 시간에 데이터를 가져온다. 또한 isEnabled의 값은 true가 된다.
// app/page.tsx
// page that fetches data
import { draftMode } from 'next/headers'
async function getData() {
const { isEnabled } from 'next/headers'
const url = isEnabled
? 'https://draft.example.com
: 'https://production.example.com'
const res = await fetch(url)
return res.json()
}
export default async function Page() {
const { title, desc } = await getData()
return (
<main>
<h1>{title}</h1>
<p>{desc}</p>
</main>
)
}
이게 다다. 헤드리스 CMS에서 또는 수동으로 초안 경로 처리기(secret과 slug를 포함해서)에 액세스 하면 이제 초안 콘텐츠를 볼 수 있다. 게시하지 않고 초안을 업데이트하는 경우 초안을 볼 수 있어야 한다. 이를 헤드리스 CMS의 초안 URL로 설정하거나 수동으로 액세스 하면 초안을 볼 수 있다.
https://<your-site>/api/draft?secret=<token>&slug=<path>
- More Details
Clear the Draft Mode cookie
기본적으로 드래프트 모드 세션은 브라우저를 닫으면 종료된다. Draft Mode 쿠키를 수동으로 지우려면 draftMode().disable()을 호출하는 Route Handler를 만든다.
// app/api/disable-draft/route.ts
import { draftMode } from 'next/headers'
export async function GET(request: Request) {
draftMode().disable()
return new Response('Draft mode is disabled')
}
그런 다음 /api/disable-draft에 요청을 보내 경로 처리기를 호출한다. next/link를 사용하여 이 경로를 호출하는 프리페치에서 실수로 쿠키를 삭제하지 않도록 prefetch={false}를 전달해야 한다.
Unique per next build
다음 빌드를 실행할 때마다 새로운 우회 쿠키 값이 생성된다. 이렇게 하면 우회 쿠키를 추측할 수 없다. HTTP를 통해 로컬에서 초안 모드를 테스트하려면 브라우저에서 서드파이 쿠키 및 로컬 스토리지 액세스를 허용해야 한다.
'Next.js' 카테고리의 다른 글
Next.js 13-2 Deploying Static Exports (0) | 2023.06.29 |
---|---|
Next.js 13-1 Deploying (0) | 2023.06.28 |
Next.js 12-6 Configuring src Directory (0) | 2023.06.26 |
Next.js 12-5 Configuring MDX (0) | 2023.06.26 |
Next.js 12-4 Configuring Absolute Imports and Module Path Aliases (0) | 2023.06.23 |