마크다운 번역

당신이 47개 페이지가 정확히 자정에 라이브로 올라가야 하는 마케팅 사이트 재설계를 배포한 적이 있다면, 콘텐츠 스테이징이 선택사항이 아니라는 것을 알 것입니다. 깔끔한 출시와 오후 11시 58분의 분주한 Slack 스레드의 차이입니다. 하지만 여기 문제가 있습니다 -- 콘텐츠 스테이징과 예약 배포를 제공하는 대부분의 CMS 플랫폼은 조건이 붙어 있습니다. 크고, 비싸고, 종속을 만드는 조건들 말입니다.

저는 지난 2년간 Social Animal에서 클라이언트를 위해 headless CMS 플랫폼, 오픈소스 도구, 커스텀 스테이징 워크플로우의 조합을 사용하여 콘텐츠 파이프라인을 구축했습니다. 제가 배운 것은 전체 콘텐츠 운영을 단일 공급업체에 맡길 필요가 없다는 것입니다. 전문가급 콘텐츠 배포를 얻으려면 오픈 인프라로 더 나은 것을 구축할 수 있습니다.

이 글은 공급업체 관리 콘텐츠 스테이징(Sanity의 Content Releases 같은)과 Supabase 기능 플래그 같은 도구로 직접 구축하는 것 사이의 실제 트레이드오프를 자세히 설명한 다음, 둘의 최고를 결합하는 방법을 보여줍니다.

목차

2025년의 콘텐츠 스테이징이 실제로 의미하는 것

콘텐츠 스테이징은 "발행 전 미리보기"를 넘어 진화했습니다. 최신 headless 아키텍처에서 콘텐츠 스테이징은 여러 콘텐츠 소스에서의 변경사항을 조율하고, 미리보기 환경에서 시각적 일관성을 보장하며, 콘텐츠 배치를 원자적으로 배포하는 것을 의미합니다 -- 모든 것이 함께 라이브로 가거나 아무것도 가지 않는다는 의미입니다.

Social Animal에서 headless CMS 개발 실무를 통해 구축하는 사이트에서 일반적인 콘텐츠 배포는 다음과 같습니다:

  • 여러 문서 변경: 동시에 발행해야 하는 10-50개의 콘텐츠 문서
  • 교차 참조 무결성: 새 카테고리를 참조하는 새 페이지가 새 저자를 참조합니다
  • 미리보기 환경: 편집자는 배포 전에 스테이징된 콘텐츠가 정확히 어떻게 보이는지 확인해야 합니다
  • 예약된 발행: 콘텐츠는 특정 시간에 라이브로 가며, 종종 마케팅 캠페인과 연결됩니다
  • 롤백 기능: 무언가가 깨지면 개별 부분이 아닌 전체 배포를 취소할 수 있어야 합니다

구식 WordPress 방식은 각 포스트를 "초안"으로 설정한 다음 대량 발행하는 것이었습니다. 블로그 포스트에는 효과적입니다. 랜딩 페이지, 문서, 가격 책정 테이블, 기능 비교에 걸쳐 제품 출시를 조율할 때는 엄청나게 무너집니다.

콘텐츠 스테이징의 세 가지 수준

모든 프로젝트가 동일한 수준의 정교함을 필요로 하는 것은 아닙니다:

수준 1: 문서당 초안/발행. 모든 CMS가 이를 가지고 있습니다. 콘텐츠가 독립적인 편집 워크플로우에는 괜찮습니다.

수준 2: 그룹화된 배포. 여러 문서가 함께 스테이징되고 원자적으로 발행됩니다. 이것이 Sanity Content Releases와 유사한 기능이 제공하는 것입니다.

수준 3: 환경 기반 스테이징. 기능 플래그가 어떤 콘텐츠 버전이 활성화되어 있는지 제어하는 전체 미리보기 환경. 이것이 오픈 인프라가 정말 빛나는 곳입니다.

대부분의 팀은 수준 2가 필요하다고 생각하지만 실제로는 수준 3이 필요합니다. 그 이유는: 수준 2는 격리된 콘텐츠 변경을 처리하지만, 실제 출시는 코드 변경, 디자인 변경, 그리고 콘텐츠 변경이 함께 일어나는 것을 포함합니다. 수준 3은 세 가지를 모두 조율할 수 있게 해줍니다.

콘텐츠 배포에서의 공급업체 종속 문제

뭔가에 대해 직설적으로 말하고 싶습니다. CMS 공급업체가 콘텐츠 스테이징을 플랫폼에 구축할 때, 그들은 선의에서 그렇게 하는 것이 아닙니다. 그것은 해자입니다. 편집 팀이 공급업체 특정 배포 관리에 의존하면, CMS 플랫폼을 전환하는 것은 전체 워크플로우를 처음부터 다시 구축하는 것을 의미합니다.

이것은 몇 가지 방식으로 나타납니다:

가격 책정 영향력. 콘텐츠 배포는 거의 항상 프리미엄 기능입니다. Sanity는 이를 Growth 플랜 뒤로 제한합니다. Contentful은 이를 Premium 계층에 넣습니다. 팀이 이에 의존하면, 공급업체는 가격을 올릴 때 당신이 어디에도 가지 않을 것임을 압니다.

워크플로우 결합. 편집자는 공급업체 특정 UI와 정신 모델을 배웁니다. 개발자는 배포 관리를 위해 공급업체 특정 API에 대한 통합을 작성합니다. CI/CD 파이프라인은 공급업체 특정 웹훅을 가집니다. 이 모든 것을 풀어헤치는 것은 3-6개월 프로젝트입니다.

제한된 커스터마이제이션. 공급업체 구현이 당신을 위해 결정을 내립니다. 두 개의 다른 CMS 인스턴스에 걸친 배포가 필요하면 어떻게 될까요? 콘텐츠 배포를 LaunchDarkly의 기능 플래그 롤아웃과 연결해야 하면 어떻게 될까요? 공급업체가 상상한 것과 일치하지 않는 승인 워크플로우가 필요하면 어떻게 될까요?

공급업체 관리 배포가 항상 잘못된 것은 아니라고 말하는 것이 아닙니다. 간단한 필요를 가진 작은 팀의 경우, 올바른 선택이 될 수 있습니다. 하지만 당신이 무엇을 트레이드하고 있는지 눈을 뜨고 시작해야 합니다.

Sanity Content Releases: 무엇을 얻고 비용이 얼마나 드는가

Sanity는 문서 변경을 함께 발행할 수 있는 명명된 배포로 그룹화하는 방법으로 Content Releases(초기 반복에서 이전에 "Spaces"라고 불림)를 도입했습니다. 그것이 잘하는 것에 대해 공정합시다.

Sanity Content Releases가 실제로 하는 것

  • 여러 문서에 대한 초안 변경을 포함하는 명명된 "배포" 생성
  • 발행하기 전에 컨텍스트의 모든 변경사항 미리보기
  • 단일 작업으로 모든 변경사항을 원자적으로 발행
  • 향후 발행을 위해 배포 예약
  • 배포 이력 보기 및 (경우에 따라) 되돌리기

개발자 경험은 탄탄합니다. Sanity의 perspective 매개변수를 사용하여 특정 배포 관점에서 콘텐츠를 쿼리합니다:

// Sanity에서 특정 배포로부터 콘텐츠 쿼리하기
import { createClient } from '@sanity/client'

const client = createClient({
  projectId: 'your-project',
  dataset: 'production',
  apiVersion: '2025-01-01',
  useCdn: false,
})

// 'summer-launch' 배포에서 나타날 때처럼 문서 가져오기
const results = await client.fetch(
  `*[_type == "landingPage"]`,
  {},
  { perspective: 'release.summer-launch' }
)

비용 현실

2025년 중반 기준으로, Content Releases에 대한 Sanity의 가격은 최소한 Growth 플랜을 필요로 합니다:

  • Free 플랜: 콘텐츠 배포 없음
  • Growth 플랜: $15/사용자/월 -- 기본 콘텐츠 배포 포함
  • Enterprise: 커스텀 가격 -- 고급 스케줄링, 승인 워크플로우 포함

8명의 편집자 팀의 경우, 그룹화된 배포를 얻기 위해 최소한 연간 $1,440을 찾고 있습니다. 이는 스테이징 워크플로우가 생성하는 추가 미리보기 쿼리에 대한 API 초과 요금 전에입니다.

비싼가요? 본질적으로는 아닙니다. 하지만 팀 규모에 따라 확장되는 반복 비용이며, 각 달이 지남에 따라 당신을 Sanity 생태계에 더 깊이 잠급니다.

Supabase를 사용한 콘텐츠용 기능 플래그 구축

여기서 일들이 흥미로워집니다. 오픈소스 Firebase 대체품인 Supabase는 공급업체 솔루션과 경쟁하는 콘텐츠 스테이징 시스템을 구축할 수 있는 원시 요소를 제공합니다. 그리고 오픈 인프라이기 때문에(자체 호스팅할 수 있음), 종속성이 없습니다.

핵심 아이디어: Supabase를 콘텐츠 기능 플래그 시스템으로 사용하여 CMS와 프론트엔드 사이에 앉으십시오. 콘텐츠는 최종 형태로 CMS에 존재하지만, Supabase는 어떤 버전의 콘텐츠가 보이는지 제어합니다.

이를 위해 Supabase를 사용하는 이유

  • 행 수준 보안(RLS): 사용자 컨텍스트(미리보기 vs. 프로덕션)를 기반으로 어떤 콘텐츠 버전이 보이는지 제어하는 정책을 생성할 수 있습니다
  • Realtime 구독: 편집자는 미리보기 환경에서 즉시 반영되는 스테이징 변경사항을 볼 수 있습니다
  • Edge Functions: 사용자에게 가깝게 커스텀 배포 로직을 배포합니다
  • 자체 호스팅 가능: Supabase Cloud에서 벗어나야 할 경우, 전체 스택을 직접 실행할 수 있습니다
  • PostgreSQL이 기저에: 스테이징 메타데이터가 독점 시스템이 아닌 실제 데이터베이스에 있습니다

기본 아키텍처

-- Supabase의 콘텐츠 배포 관리
CREATE TABLE content_releases (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  name TEXT NOT NULL,
  status TEXT DEFAULT 'draft' CHECK (status IN ('draft', 'staged', 'published', 'rolled_back')),
  scheduled_at TIMESTAMPTZ,
  published_at TIMESTAMPTZ,
  created_by UUID REFERENCES auth.users(id),
  created_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE release_items (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  release_id UUID REFERENCES content_releases(id) ON DELETE CASCADE,
  cms_document_id TEXT NOT NULL,  -- Sanity/Contentful/무엇이든 참조
  cms_type TEXT NOT NULL,
  content_snapshot JSONB,  -- 스테이징 시점의 콘텐츠 스냅샷
  created_at TIMESTAMPTZ DEFAULT now()
);

CREATE TABLE feature_flags (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  key TEXT UNIQUE NOT NULL,
  enabled BOOLEAN DEFAULT false,
  release_id UUID REFERENCES content_releases(id),
  metadata JSONB DEFAULT '{}',
  updated_at TIMESTAMPTZ DEFAULT now()
);

이것은 당신의 CMS 공급업체와 완전히 독립적인 배포 관리 시스템을 제공합니다. 내년에 Sanity를 Contentful로 전환합니까? 배포 관리는 전혀 변경되지 않습니다.

직접 비교: Supabase 기능 플래그 vs Sanity Content Releases

이 접근법을 정직하게 비교해 봅시다:

요소 Sanity Content Releases Supabase 기능 플래그
설정 시간 몇 분 (내장) 몇 일 (커스텀 구축)
월간 비용 (8명 편집자) ~$120/월 (Growth 플랜) ~$25/월 (Supabase Pro)
공급업체 종속 높음 (Sanity 특정) 낮음 (PostgreSQL + 오픈소스)
미리보기 경험 우수 (네이티브 Studio) 좋음 (커스텀 미리보기 필요)
교차 CMS 배포 아니오 (Sanity만) 예 (CMS 무관)
코드 + 콘텐츠 배포 아니오 예 (배포 플래그와 연결)
스케줄링 내장 (Growth+) 커스텀 (Edge Functions + cron)
롤백 부분 완전 (로직 제어)
편집 UX 광택남 구현에 따라 다름
자체 호스팅 가능 아니오
승인 워크플로우 Enterprise만 커스텀 (필요한 것을 구축)

트레이드오프는 명확합니다: Sanity는 광택나고 준비된 경험을 제공합니다. Supabase는 유연성과 독립성을 제공하지만, 편집 인터페이스를 직접 구축해야 합니다.

아키텍처: 오픈 인프라 콘텐츠 스테이징 파이프라인

공급업체 의존성 없이 심각한 콘텐츠 스테이징이 필요한 클라이언트를 위해 정착한 아키텍처입니다. 우리는 Next.js 개발 프로젝트Astro 빌드에서 이 패턴을 자주 사용합니다.

흐름

  1. 콘텐츠 작성은 모든 headless CMS에서 발생합니다 (Sanity, Contentful, Strapi -- 상관없음)
  2. CMS 웹훅이 콘텐츠 변경 시 실행되어 메타데이터를 Supabase로 푸시합니다
  3. Supabase가 배포 그룹을 저장합니다 -- 어떤 콘텐츠 변경이 어떤 배포에 속하는지
  4. 미리보기 환경이 Supabase를 쿼리하여 어떤 콘텐츠 버전을 표시할지 결정합니다
  5. 배포 트리거 (수동, 예약 또는 API 기반)가 Supabase의 기능 플래그를 전환합니다
  6. ISR/온디맨드 재검증이 Next.js 또는 Astro에서 영향을 받은 페이지를 다시 빌드합니다
  7. 롤백이 기능 플래그를 되돌리고 다른 재검증을 트리거합니다

핵심 통찰력

CMS는 배포에 대해 알 필요가 없습니다. 콘텐츠는 CMS의 발행 또는 초안 상태로 존재하기만 합니다. Supabase가 트래픽 관제자로 작동하여 프론트엔드가 어떤 콘텐츠 버전을 렌더링할지 결정합니다.

이 분리는 믿을 수 없을 정도로 강력합니다. 이를 통해 다음을 수행할 수 있습니다:

  • Sanity의 무료 계층을 사용하면서도 콘텐츠 배포를 얻습니다
  • 여러 CMS 인스턴스에 걸친 배포를 조율합니다
  • 동일한 기능 플래그 시스템을 통해 콘텐츠 배포를 코드 배포와 연결합니다
  • CMS 공급업체를 전환하면서 배포 파이프라인을 재구축하지 않습니다

구현 가이드

이 시스템의 핵심을 구축해 봅시다. 대부분의 클라이언트가 사용하는 프론트엔드 프레임워크이므로 Next.js를 사용하겠지만, 이 패턴은 모든 프레임워크와 작동합니다.

단계 1: Supabase 배포 관리자

// lib/releases.ts
import { createClient } from '@supabase/supabase-js'

const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_SERVICE_KEY!
)

export async function createRelease(name: string) {
  const { data, error } = await supabase
    .from('content_releases')
    .insert({ name, status: 'draft' })
    .select()
    .single()

  if (error) throw error
  return data
}

export async function addToRelease(
  releaseId: string,
  cmsDocumentId: string,
  cmsType: string,
  contentSnapshot: Record<string, unknown>
) {
  const { error } = await supabase
    .from('release_items')
    .insert({
      release_id: releaseId,
      cms_document_id: cmsDocumentId,
      cms_type: cmsType,
      content_snapshot: contentSnapshot,
    })

  if (error) throw error
}

export async function publishRelease(releaseId: string) {
  // 원자적으로 발행: 배포 상태 업데이트 및 기능 플래그 활성화
  const { error: releaseError } = await supabase
    .from('content_releases')
    .update({ status: 'published', published_at: new Date().toISOString() })
    .eq('id', releaseId)

  if (releaseError) throw releaseError

  const { error: flagError } = await supabase
    .from('feature_flags')
    .update({ enabled: true, updated_at: new Date().toISOString() })
    .eq('release_id', releaseId)

  if (flagError) throw flagError

  // 영향을 받은 페이지에 대해 재검증 트리거
  await triggerRevalidation(releaseId)
}

단계 2: 콘텐츠 해결 미들웨어

이것이 마법이 일어나는 곳입니다. 데이터 페칭 레이어가 Supabase 기능 플래그를 확인하여 어떤 콘텐츠 버전을 제공할지 결정합니다:

// lib/content-resolver.ts
import { createClient as createSanityClient } from '@sanity/client'
import { createClient as createSupabaseClient } from '@supabase/supabase-js'

const sanity = createSanityClient({
  projectId: process.env.SANITY_PROJECT_ID!,
  dataset: 'production',
  apiVersion: '2025-01-01',
  useCdn: true,
})

const supabase = createSupabaseClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_ANON_KEY!
)

export async function resolveContent(
  documentId: string,
  isPreview: boolean = false,
  previewReleaseId?: string
) {
  // 이 문서를 포함하는 활성 배포가 있는지 확인
  let releaseContent = null

  if (isPreview && previewReleaseId) {
    // 미리보기 모드에서 특정 배포로부터 스테이징된 콘텐츠 표시
    const { data } = await supabase
      .from('release_items')
      .select('content_snapshot')
      .eq('release_id', previewReleaseId)
      .eq('cms_document_id', documentId)
      .single()

    releaseContent = data?.content_snapshot
  } else {
    // 프로덕션에서 이 문서를 무시하는 발행된 배포가 있는지 확인
    const { data } = await supabase
      .from('release_items')
      .select('content_snapshot, content_releases!inner(status)')
      .eq('cms_document_id', documentId)
      .eq('content_releases.status', 'published')
      .order('created_at', { ascending: false })
      .limit(1)
      .single()

    releaseContent = data?.content_snapshot
  }

  if (releaseContent) {
    return releaseContent
  }

  // 표준 CMS 콘텐츠로 폴백
  return sanity.fetch(`*[_id == $id][0]`, { id: documentId })
}

단계 3: Supabase Edge Functions를 사용한 예약된 배포

// supabase/functions/publish-scheduled/index.ts
import { createClient } from '@supabase/supabase-js'

Deno.serve(async () => {
  const supabase = createClient(
    Deno.env.get('SUPABASE_URL')!,
    Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
  )

  // 이제 또는 그 이전에 예약되었으나 아직 발행되지 않은 배포를 찾기
  const { data: dueReleases } = await supabase
    .from('content_releases')
    .select('id, name')
    .eq('status', 'staged')
    .lte('scheduled_at', new Date().toISOString())

  if (!dueReleases?.length) {
    return new Response(JSON.stringify({ published: 0 }), {
      headers: { 'Content-Type': 'application/json' },
    })
  }

  for (const release of dueReleases) {
    await supabase
      .from('content_releases')
      .update({ status: 'published', published_at: new Date().toISOString() })
      .eq('id', release.id)

    await supabase
      .from('feature_flags')
      .update({ enabled: true })
      .eq('release_id', release.id)

    console.log(`Published release: ${release.name}`)
  }

  return new Response(
    JSON.stringify({ published: dueReleases.length }),
    { headers: { 'Content-Type': 'application/json' } }
  )
})

이를 매 분마다 실행되는 Supabase cron 작업으로 설정하고, 예약된 배포가 완성됩니다.

단계 4: 미리보기 경로

Next.js App Router에서:

// app/api/preview/route.ts
import { draftMode } from 'next/headers'
import { redirect } from 'next/navigation'

export async function GET(request: Request) {
  const { searchParams } = new URL(request.url)
  const releaseId = searchParams.get('release')
  const slug = searchParams.get('slug') || '/'

  if (!releaseId) {
    return new Response('Missing release parameter', { status: 400 })
  }

  const draft = await draftMode()
  draft.enable()

  // 배포 ID를 쿠키에 저장하여 콘텐츠 해석기가 사용합니다
  const response = redirect(slug)
  response.headers.set(
    'Set-Cookie',
    `preview-release=${releaseId}; Path=/; HttpOnly; SameSite=Lax`
  )

  return response
}

이제 편집자는 /api/preview?release=summer-launch&slug=/products를 방문하여 모든 배포를 미리볼 수 있습니다. 그들은 그 배포가 라이브로 갈 때 사이트가 정확히 어떻게 보일지 볼 것입니다.

각각을 언제 사용할지

나는 모든 상황에 맞는 답을 믿지 않습니다. 여기 제 정직한 권고사항입니다:

Sanity Content Releases를 사용할 때:

  • 팀이 작습니다 (편집자 5명 미만)
  • 당신은 이미 Sanity에 장기간 전념했습니다
  • 콘텐츠 배포가 간단합니다 (교차 시스템 조율이 필요하지 않음)
  • 커스텀 도구를 구축할 개발자 대역폭이 없습니다
  • 예산이 주요 관심사가 아닙니다

Supabase 기능 플래그로 구축할 때:

  • 콘텐츠 + 코드 배포를 함께 조율해야 합니다
  • 여러 CMS 플랫폼을 사용하거나 향후 전환할 계획입니다
  • 팀은 공급업체 도구가 지원하지 않는 특정 워크플로우 요구사항이 있습니다
  • 배포 관리 인프라를 자체 호스팅하고 싶습니다
  • 장기 비용과 독립성이 설정 속도보다 더 중요합니다

하이브리드 접근법을 사용할 때:

  • Sanity의 편집 경험을 원하지만 교차 시스템 배포 조율이 필요합니다
  • CMS 플랫폼 간에 마이그레이션 중이며 배포 관리가 전환을 견뎌야 합니다
  • 콘텐츠와 애플리케이션 동작 모두에 영향을 미치는 세밀한 기능 플래그가 필요합니다

하이브리드 접근법은 실제로 headless CMS 계약에서 가장 자주 권장하는 것입니다. 개별 문서에 대해 CMS의 네이티브 초안/발행을 사용하고, 조율된 배포 및 기능 플래깅을 위해 맨 위에 Supabase를 겹칩니다.

FAQ

headless CMS에서 콘텐츠 스테이징이 정확히 무엇인가요?

콘텐츠 스테이징은 콘텐츠 변경사항을 라이브로 가기 전에 준비, 미리보기 및 그룹화하는 프로세스입니다. headless 아키텍처에서, 이는 여러 API 기반 콘텐츠 소스 간에 초안 콘텐츠를 관리하고 미리보기 환경이 발행된 콘텐츠가 어떻게 보일지 정확히 반영하도록 보장하는 것을 의미합니다. 단순 초안/발행 토글을 넘어갑니다 -- 실제 스테이징은 원자적으로 발행되는 관련 변경 그룹화를 포함합니다.

Supabase가 정말 충분히 저렴하여 유료 CMS 기능을 대체할 수 있나요?

Supabase의 무료 계층은 500MB의 데이터베이스 저장소, 50,000명의 월간 활성 사용자, 500,000개의 Edge Function 호출을 제공합니다. 콘텐츠 스테이징 메타데이터(배포 그룹 및 기능 플래그 -- 콘텐츠 자체가 아님)의 경우, 대부분의 팀에게 충분합니다. $25/월의 Pro 플랜은 훨씬 더 큰 작업을 다룹니다. CMS 프리미엄 기능에 대해 사용자당 지불하는 것과 비교하면, 3-4명 편집자보다 큰 팀의 경우 수학이 빠르게 작동합니다.

Contentful, Strapi 또는 다른 CMS 플랫폼과 함께 이 접근법을 사용할 수 있나요?

절대로. 그것이 전부입니다. Supabase가 CMS와 프론트엔드 사이의 독립적인 레이어로 앉아 있기 때문에, 콘텐츠가 어디에서 오는지는 중요하지 않습니다. 우리는 Sanity, Contentful, Hygraph, 심지어 WordPress를 콘텐츠 소스로 이 패턴을 구현했습니다. 콘텐츠 해석기 미들웨어는 특정 CMS를 가져오는 방법을 알기만 하면 됩니다.

기능 플래그 접근법으로 롤백을 어떻게 처리하나요?

실제로 롤백은 기능 플래그를 사용하면 공급업체 관리 배포보다 더 간단합니다. 기능 플래그를 다시 비활성화로 전환하고, 영향을 받은 페이지의 재검증을 트리거하고, 완료되었습니다. Supabase에 저장된 콘텐츠 스냅샷은 롤백 포인트로 제공됩니다. 반면에, 공급업체 관리 롤백은 종종 개별 부분이 아닌 이전 문서 버전을 다시 발행해야 합니다.

이것이 정적 사이트 생성기 및 ISR로 작동하나요?

예, 특히 잘 작동합니다. ISR(증분 정적 재생성)이 있는 Next.js 또는 Astro의 하이브리드 렌더링의 경우, 배포가 발행될 때 온디맨드 재검증을 트리거합니다. 재검증 API가 콘텐츠 해석기를 호출하고, 이제 새로 발행된 콘텐츠를 반환하며, 영향을 받은 페이지가 다시 생성됩니다. 우리는 Next.js 개발 서비스Astro 개발 서비스를 사용하는 클라이언트를 위해 우리의 접근법을 상세히 문서화했습니다.

배포를 관리하기 위한 편집 UI를 어떻게 구축하나요?

몇 가지 옵션이 있습니다. 가장 빠른 것은 Supabase의 자동 생성 REST API와 Shadcn/UI 같은 React 컴포넌트 라이브러리를 사용하여 간단한 관리 패널을 구축하는 것입니다. 사용 가능한 것을 구축하는 데 2-3일이 걸립니다. 더 많은 광택을 위해, Supabase 배포 관리 API와 통신하는 커스텀 플러그인으로 Sanity Studio를 확장할 수 있습니다. 우리는 또한 시간 내에 배포 대시보드를 만들기 위해 Retool 또는 유사한 내부 도구 빌더를 사용하는 팀을 봤습니다.

고유한 콘텐츠 스테이징 시스템을 구축하는 위험성은 무엇인가요?

가장 큰 위험은 유지 관리 부담입니다. 공급업체 관리 기능은 버그 수정, 성능 개선 및 새로운 기능을 자동으로 얻습니다. 당신이 직접 구축할 때, 당신은 이 모든 것의 소유자입니다. 두 번째 위험은 엣지 케이스 -- 두 배포가 동일한 문서를 수정할 때 충돌 해결 같은 것, 또는 특정 코드 변경이 필요한 배포 처리. 이들은 해결 가능한 문제이지만, 사려 깊은 엔지니어링이 필요합니다. 팀에 그 수용력이 없으면, 공급업체 솔루션이 더 안전한 내기입니다. 당신의 팀 요구사항에 맞는 커스텀 스테이징 파이프라인 설계에 도움이 필요하면, 저희에게 연락하세요.

규모에서 -- 20명 이상의 편집자들이 라고 한다면 -- 가격 책정은 어떻게 비교되나요?

Sanity Growth에서 20명의 편집자 ($15/사용자/월) 시, 콘텐츠 배포를 포함하는 플랜만 해도 연간 $3,600을 지출합니다. Supabase Pro at $25/월 ($300/년) 더하기 Edge Functions에서 $50/월 및 추가 데이터베이스 사용량, 당신은 대략 $900/년입니다. Enterprise 규모에서 간격이 더 넓어집니다. 하지만 커스텀 시스템을 구축하고 유지하는 개발 비용을 계산에 포함하는 것을 기억하십시오 -- 일반적으로 40-80시간 앞서고 월 2-4시간 진행 중입니다. 당신의 특정 상황에 대한 비용 분석은, 가격 책정 페이지를 확인하세요.