주소 이동 (커스텀 리다이렉트) 연동
어드민(admin.roottale.com)의 설정 > 주소 이동에서 운영자가 정의한 임의
경로 이동 규칙(/old-event → /promo)을 사이트 Proxy로 적용합니다. 코드
수정 없이 고객이 직접 규칙을 추가·수정·삭제할 수 있습니다.
두 종류의 주소 이동이 있습니다.
- 글 주소 변경 자동 301 — 블로그 글의 슬러그를 바꾸면 자동으로 옛 주소가
새 주소로 이어집니다. 글 라우트에서 처리되며 별도 설정이 필요 없습니다
(
blog.md의postRedirectPath참고). - 커스텀 리다이렉트(이 문서) — 글이 아닌 임의 경로를 옮깁니다. 라우팅 이전 단계인 Proxy에서만 가로챌 수 있어, 아래 설정이 필요합니다.
글의 공개 주소가 바뀌면(slug 변경·분류 이동·모델 규칙 변경) 플랫폼이 옛 경로 → 현재
경로 301 을 자동으로 이 목록에 더합니다(id 가 path-history: 로 시작). 운영자가
같은 출발 경로 규칙을 만들었으면 운영자 규칙이 이깁니다. Proxy를 쓰고 있다면 별도
작업 없이 옛 링크가 새 주소로 갑니다.
규칙은 GET /v1/cms/public/redirects 로 내려오며 활성 규칙만 포함됩니다
(api-reference.md). 출발 경로는 정규화된 사이트 내부 절대 경로, 도착지는
내부 경로 또는 절대 URL, 상태는 301(영구) 또는 302(임시)입니다.
Proxy 설정
@roottale/cms-renderer-next 의 createRedirectMiddleware 를 프로젝트 루트
proxy.ts 에 마운트합니다. 규칙을 자동 캐시(기본 60초)하며, API 실패 시
기존 캐시가 있으면 오래된 규칙을 우선 사용하고(stale-first), 캐시가
없으면 트래픽을 막지 않고 통과시킵니다(fail-soft).
// proxy.ts
import { NextResponse } from "next/server";
import { createRedirectMiddleware } from "@roottale/cms-renderer-next/routes";
const redirects = createRedirectMiddleware({
apiKey: process.env.ROOTTALE_API_KEY!,
// apiBase, siteId, cacheTtlMs 는 선택.
});
export async function proxy(req: Request) {
return (await redirects(req)) ?? NextResponse.next();
}
// Next 내부·API·알려진 정적 자산만 제외합니다. 점 포함 경로를 전부 막으면
// `/old.html`·`/foo.php` 같은 레거시 마이그레이션 리다이렉트가 동작하지
// 않으므로, 자산 확장자만 명시적으로 제외합니다.
export const config = {
matcher: [
"/((?!_next/|api/|.*\\.(?:ico|png|jpg|jpeg|gif|svg|webp|css|js|txt|xml|json|woff2?|map)$).*)",
],
};
ROOTTALE_API_KEY는 블로그 조회와 같은 키입니다. 서버 전용 — 절대 브라우저에 노출하지 마세요.- 매칭은 정확 경로 일치입니다(와일드카드 없음). 출발 경로의 앞/뒤 슬래시와 한글 percent-encoding 차이는 자동 정규화해 비교합니다.
- 도착지가 내부 경로면 요청 origin 기준 절대 URL 로 변환해 리다이렉트합니다.
- 내부 경로 체인은 최종 도착지로 평탄화하고, 순환이 발견되면 브라우저 왕복을 막기 위해 해당 요청을 통과시킵니다.
- 매칭이 없으면
null을 반환하므로NextResponse.next()로 통과시키세요.
Site Materializer로 새 사이트를 만들면 proxy.ts와
tests/redirect-proxy.test.ts가 필수 산출물로 포함됩니다. 두 파일은
내부 Materializer 영수증에도 기록되므로, 설치 여부를 추측하지 않고
실제 납품 산출물로 확인할 수 있습니다.
캐시와 즉시성
규칙은 Proxy가 TTL(기본 60초) 동안 캐시합니다. 운영자가 규칙을 바꾸면
최대 TTL 만큼 뒤 반영됩니다. 더 빠른 반영이 필요하면 cacheTtlMs 를 줄이세요
(요청당 API 호출이 늘어납니다).
const redirects = createRedirectMiddleware({
apiKey: process.env.ROOTTALE_API_KEY!,
cacheTtlMs: 10_000, // 10초
});
직접 호출 (Proxy 없이)
규칙 목록만 필요하면 fetchRedirects 로 직접 가져올 수 있습니다.
import { fetchRedirects } from "@roottale/cms-client/server";
const rules = await fetchRedirects({ apiKey: process.env.ROOTTALE_API_KEY! });
// [{ id, fromPath, toTarget, statusCode }]