Next.js로 대규모 SaaS를 위한 중앙 집중식 액션 구축
Source: Dev.to
아키텍처 개요
대규모 SaaS 프로젝트에서는 각 모듈마다 서버 액션을 개별적으로 처리하면 코드 중복이 발생합니다.
중앙 집중형 뮤테이션 엔진은 모든 API 뮤테이션을 하나의 재사용 가능한 함수로 통합합니다. 인증, 권한 부여, 상점/서브도메인 컨텍스트, 요청 페이로드, fetch 실행, 캐시 재검증을 처리합니다.
핵심 유틸리티
- logger – 디버깅 및 모니터링을 위한 구조화된 로깅.
- resolveModelName –
saved-attribute와 같은 라우트명을saved_attribute로 변환. - hasPermission & parseAccessRules – 사용자가 특정 작업을 수행할 수 있는지 확인하는 RBAC 구현.
- getBaseUrlWithSubdomain – 상점 서브도메인에 따라 올바른 API 기본 URL을 해결.
인증 처리
if (requireAuth) {
const accessToken = cookieStore.get("accessToken")?.value;
if (!accessToken) {
return { message: "You are not authorized to perform this action!" };
}
// Validate JWT access token...
}
상점 / 서브도메인 컨텍스트
if (requireShopId) {
const subdomain = cookieStore.get("shopSubdomain")?.value;
if (!subdomain) {
return { message: "Shop identifier not found!" };
}
// Use subdomain for multi‑tenant routing...
}
역할 기반 접근 제어 (RBAC)
const rulesRaw = cookieStore.get("accessRules")?.value;
const rules = parseAccessRules(rulesRaw);
const model = resolveModelName(route.split("/")[1]);
const action = methodToAction[method];
if (!hasPermission(rules, model, action)) {
return { success: false, message: "Permission denied" };
}
HTTP 메서드 → CRUD 작업 매핑.
동적 페이로드 처리
let body: string | undefined = undefined;
if (method === "DELETE" && ids?.length) {
body = JSON.stringify({ ids });
} else if (method !== "DELETE" && data) {
body = data;
}
단일 ID 삭제, 대량 삭제, POST/PUT 페이로드를 지원.
Fetch 실행
const response = await fetch(url, {
method,
headers,
body,
cache: "no-store",
});
const result = await response.json();
신선한 데이터(no-store)로 서버‑사이드 뮤테이션을 실행.
캐시 재검증
paths.forEach(path => typeof path === "string" && revalidatePath(path));
tags.forEach(tag => typeof tag === "string" && revalidateTag(tag));
뮤테이션 후 Next.js 경로나 태그를 자동으로 재검증.
오류 처리 및 로깅
try {
// ...mutation logic...
} catch (error) {
logger(error);
return { success: false, message: "An error occurred during the mutation." };
}
오류 처리를 표준화.
장점
- 재사용성 – 모든 모델에 대한 단일 뮤테이션 핸들러.
- 보안 – 전역 RBAC 적용.
- 멀티‑테넌트 지원 – 상점‑특정 서브도메인 처리.
- 일관성 – 통합 로깅, 오류 처리, 캐시 재검증.
- 확장성 – SaaS가 성장함에 따라 쉽게 확장 가능.
사용 예시
await mutation({
route: "/customer",
method: "POST",
data: JSON.stringify({ name: "John Doe" }),
pathToRevalidate: "/customers",
tagsToRevalidate: ["customer‑list"],
});
인증, RBAC, 페이로드, 캐시 무효화를 한 번에 처리.
흐름도
┌────────────────────┐
│ Client / Frontend │
│ (React / Next.js) │
└─────────┬──────────┘
│
▼
┌────────────────────┐
│ Server Action Call│
│ mutation(params) │
└─────────┬──────────┘
│
┌────────┴─────────┐
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ AUTHENTICATION│ │ SHOP / SUBDOMAIN│
│ check JWT token│ │ get shop identifier│
│ from cookies │ │ from cookies │
└───────┬───────┘ └───────┬───────┘
│ │
└───────┬─────────┘
▼
┌─────────────────────┐
│ ROLE‑BASED ACCESS │
│ CONTROL (RBAC) │
│ hasPermission() │
│ parseAccessRules() │
└───────┬─────────────┘
▼
┌─────────────────────┐
│ Construct Headers │
│ - Authorization │
│ - x‑app‑identifier │
└───────┬─────────────┘
▼
┌─────────────────────┐
│ Determine Payload │
│ - DELETE ids array │
│ - POST / PUT data │
└───────┬─────────────┘
▼
┌─────────────────────┐
│ FETCH Request │
│ method, headers, │
│ body │
└───────┬─────────────┘
▼
┌─────────────────────┐
│ Response Handling │
│ - parse JSON │
│ - log errors │
└───────┬─────────────┘
▼
┌───────────────┬───────────────┐
▼ ▼ ▼
┌───────┐ ┌───────┐ ┌───────┐
│ PATH │ │ TAG │ │ CLIENT│
│ REVAL │ │ REVAL │ │ UI │
└───────┘ └───────┘ └───────┘
정리
- 중앙 집중형 서버 액션은 보일러플레이트를 줄이고 유지보수성을 향상시킵니다.
- RBAC는 모든 API 뮤테이션에 일관된 보안을 보장합니다.
- 서브도메인 인식 멀티‑테넌트 아키텍처는 SaaS 확장성을 지원합니다.
- 자동 캐시 재검증으로 UI가 항상 최신 데이터를 표시합니다.
대규모 SaaS 프로젝트에 중앙 집중형 뮤테이션 엔진을 구현하면 코드 유지보수성, 보안, 확장성이 크게 향상됩니다. 인증, RBAC, 멀티‑테넌트 서브도메인 처리, 페이로드 관리, 캐시 재검증을 하나의 서버 액션에 통합함으로써 개발자는:
- 여러 엔드포인트에 걸친 반복 코드를 제거합니다.
- 동적 권한 검사를 통해 일관된 보안을 적용합니다.
- 서브도메인 기반 API 호출을 통해 멀티‑테넌트 아키텍처를 효율적으로 지원합니다.
- Next.js 경로와 태그를 자동으로 재검증하여 UI 일관성을 보장합니다.
- SaaS가 성장함에 따라 새로운 모델과 액션을 최소한의 마찰로 추가할 수 있어 쉽게 확장할 수 있습니다.