2026년 Payload CMS vs Directus: 코드 우선 vs 데이터베이스 우선

2026년에 헤드리스 CMS 프로젝트를 구축하고 있으며 Payload CMS와 Directus로 옵션을 좁혔다면, 축하합니다 — 좋은 선택입니다. 둘 다 오픈소스이고 자체 호스팅 가능하며 Node.js로 구축되었습니다. 둘 다 활발한 커뮤니티가 있고 빠르게 기능을 출시하고 있습니다. 하지만 콘텐츠 스키마가 어떻게 생성되어야 하는지에 대한 근본적으로 다른 철학을 나타내며, 그 차이는 프로젝트에서 하는 모든 결정에 영향을 미칩니다.

저는 지난 2년간 둘 다를 사용하여 프로덕션 사이트를 출시했습니다. 마케팅 페이지에서 말하는 것이 아니라 실제로 생각하는 것을 여기에 나타냅니다.

목차

Payload CMS vs Directus in 2026: Code-First vs Database-First

핵심 철학의 분기

이것이 가장 중요한 것이므로 명확하게 표현하겠습니다:

Payload CMS는 코드 우선입니다. TypeScript 구성 파일에서 스키마를 정의합니다. 데이터베이스는 코드에 맞춰집니다.

Directus는 데이터베이스 우선입니다. 기존 데이터베이스를 지정할 수 있으며 스키마를 내재합니다. 관리 UI는 데이터베이스에 맞춰집니다.

어느 접근 방식도 객관적으로 더 나은 것은 아닙니다. 하지만 하나는 당신의 프로젝트에 극적으로 더 나을 것이고, 이것을 잘못 이해하면 나중에 고통을 겪게 됩니다.

개발자이고 그린필드 프로젝트를 구축 중이며 CMS 스키마를 애플리케이션 코드와 함께 버전 관리하려면, Payload가 가정처럼 느껴질 것입니다. 200개의 테이블이 있는 기존 PostgreSQL 데이터베이스가 있고 위에 콘텐츠 관리 레이어가 필요하다면, Directus는 몇 주를 절약해줄 것입니다.

스키마 설계: 코드 우선 vs 데이터베이스 우선

Payload의 코드 우선 접근 방식

Payload 3.x (2026년 현재 주요 버전)에서는 TypeScript 구성 파일에서 컬렉션을 정의합니다:

// collections/Posts.ts
import type { CollectionConfig } from 'payload'

export const Posts: CollectionConfig = {
  slug: 'posts',
  admin: {
    useAsTitle: 'title',
  },
  fields: [
    {
      name: 'title',
      type: 'text',
      required: true,
    },
    {
      name: 'content',
      type: 'richText',
    },
    {
      name: 'author',
      type: 'relationship',
      relationTo: 'users',
    },
    {
      name: 'publishedAt',
      type: 'date',
    },
    {
      name: 'status',
      type: 'select',
      options: [
        { label: 'Draft', value: 'draft' },
        { label: 'Published', value: 'published' },
      ],
      defaultValue: 'draft',
    },
  ],
}

이 구성은 당신의 진실의 근원입니다. Payload가 시작되면 데이터베이스 마이그레이션을 자동으로 생성합니다 (Payload 3.x는 PostgreSQL 또는 SQLite 지원을 통해 내부적으로 Drizzle ORM을 사용하며 여전히 MongoDB를 지원합니다). 스키마는 Git에 있습니다. PR에서 스키마 변경 사항을 검토합니다. 애플리케이션 코드에 사용할 동일한 워크플로우이며, 그것이 포인트입니다.

Payload는 또한 이러한 구성에서 TypeScript 타입을 자동으로 생성합니다. 따라서 Next.js 프론트엔드에서 posts를 쿼리할 때, 별도의 타입 정의를 유지할 필요 없이 완전한 타입 안전성을 얻습니다.

Directus의 데이터베이스 우선 접근 방식

Directus는 반대의 입장을 취합니다. 다음을 수행할 수 있습니다:

  1. Directus를 기존 데이터베이스로 지정하면 스키마를 읽습니다
  2. 관리 UI를 통해 컬렉션을 생성하면 SQL 마이그레이션이 생성됩니다
  3. Directus SDK를 사용하여 프로그래매틱하게 스키마를 관리합니다
// Directus SDK를 통해 컬렉션 생성
import { createDirectus, rest, createCollection } from '@directus/sdk'

const client = createDirectus('http://localhost:8055').with(rest())

await client.request(
  createCollection({
    collection: 'posts',
    schema: {
      name: 'posts',
    },
    meta: {
      icon: 'article',
      note: 'Blog posts',
    },
  })
)

Directus 11 (2025년 말 릴리스)은 스키마 마이그레이션 도구를 크게 개선했습니다. 이제 스키마 스냅샷을 YAML 파일로 내보내고 가져올 수 있어 버전 제어가 이전보다 훨씬 더 실용적입니다:

# 현재 스키마 내보내기
npx directus schema snapshot ./schema-snapshot.yaml

# 스키마 차이를 다른 환경에 적용
npx directus schema apply ./schema-snapshot.yaml

하지만 솔직한 진실은: 이러한 개선에도 불구하고 Directus 스키마 관리는 Git 워크플로우에서 Payload의 접근 방식만큼 자연스럽지 않습니다. 의도를 선언하기보다는 상태를 스냅샷하고 있습니다.

스키마 비교표

측면 Payload CMS Directus
스키마 진실의 근원 TypeScript 구성 파일 데이터베이스 자체
스키마 버전 관리 네이티브 Git 워크플로우 YAML 스냅샷 (v11에서 개선)
기존 데이터베이스 지원 제한적 (마이그레이션 경로) 우수함 (내재)
자동 생성 타입 예, 구성에서 예, SDK + CLI 경유
데이터베이스 지원 PostgreSQL, SQLite, MongoDB PostgreSQL, MySQL, MariaDB, SQLite, MS SQL, CockroachDB, OracleDB
ORM / 쿼리 레이어 Drizzle ORM (v3) 사용자 정의 쿼리 엔진 (Knex 기반)
마이그레이션 생성 구성 변경에서 자동 스키마 차이 스냅샷

TypeScript 및 개발자 경험

Payload의 TypeScript 스토리

Payload는 뼛속까지 TypeScript입니다. 전체 프로젝트는 TypeScript로 작성되고 TypeScript로 구성되며 TypeScript를 생성합니다. payload generate:types를 실행하면 모든 컬렉션에 대한 인터페이스를 얻습니다:

// 자동 생성됨
export interface Post {
  id: string
  title: string
  content?: RichTextContent
  author?: string | User
  publishedAt?: string
  status?: 'draft' | 'published'
  createdAt: string
  updatedAt: string
}

이러한 타입은 Local API, REST API 응답 및 GraphQL 쿼리로 흐릅니다. Payload 3.x에서는 Next.js 앱 내부에서 실행되므로 이러한 타입을 직접 가져오고 사용할 수 있습니다. 별도의 SDK가 필요하지 않습니다. 서버측 렌더링을 위한 API 호출이 없습니다 — 데이터베이스를 직접 쿼리하고 있습니다:

// Next.js 서버 컴포넌트에서
import { getPayload } from 'payload'
import config from '@payload-config'

export default async function BlogPage() {
  const payload = await getPayload({ config })
  
  const posts = await payload.find({
    collection: 'posts',
    where: {
      status: { equals: 'published' },
    },
  })
  // posts.docs는 Post[]로 완전히 타입화됨
  
  return <PostList posts={posts.docs} />
}

이것은 정말로 뛰어난 DX입니다. 네트워크 홉이 없고, 완전한 타입이며, 그냥 함수입니다.

Directus의 TypeScript 스토리

Directus는 TypeScript 지원을 크게 개선했습니다. @directus/sdk 패키지는 일반 타입 매개변수를 지원합니다:

import { createDirectus, rest, readItems } from '@directus/sdk'

interface Schema {
  posts: Post[]
  users: User[]
}

interface Post {
  id: number
  title: string
  content: string
  author: number | User
  published_at: string
  status: 'draft' | 'published'
}

const client = createDirectus<Schema>('http://localhost:8055').with(rest())

const posts = await client.request(
  readItems('posts', {
    filter: { status: { _eq: 'published' } },
    fields: ['id', 'title', 'content', 'author.*'],
  })
)

문제는? 이러한 타입 정의를 직접 작성하고 유지해야 합니다 (directus-typescript-gen 같은 커뮤니티 도구로 생성하거나). 타입은 Payload가 하는 것과 같은 방식의 첫 번째 클래스 방식으로 스키마에서 자동으로 파생되지 않습니다. 이것은 데이터베이스 우선의 절충입니다: 데이터베이스는 TypeScript를 모릅니다.

Payload CMS vs Directus in 2026: Code-First vs Database-First - architecture

API 레이어 및 쿼리 기능

둘 다 REST 및 GraphQL API를 생성하지만 맛이 다릅니다.

Payload는 다음을 제공합니다:

  • 관계에 대한 깊이 제어가 있는 REST API
  • GraphQL API (구성에서 자동 생성)
  • Local API (직접 데이터베이스 쿼리, HTTP 오버헤드 없음)
  • 전체 쿼리 연산자: equals, not_equals, greater_than, in, contains 등

Directus는 다음을 제공합니다:

  • 세분화된 필드 선택이 있는 REST API
  • GraphQL API (스키마 내재에서 자동 생성)
  • Directus SDK (REST를 래핑하고, 인터페이스를 제공하면 타입화됨)
  • _eq, _neq, _gt, _in, _contains, 논리 _and/_or 연산자를 사용한 풍부한 필터링
  • API에 내장된 집계 쿼리 (count, sum, avg 등)

Directus는 복잡한 쿼리, 특히 집계에 대한 API 유연성에서 약간의 우위가 있습니다. GROUP BY 스타일 쿼리를 API를 통해 수행해야 한다면, Directus가 기본적으로 처리합니다. Payload를 사용하면 일반적으로 Drizzle ORM 레이어로 내려가거나 사용자 정의 엔드포인트를 작성합니다.

Payload의 치명적 장점은 Local API입니다. CMS와 Next.js 프론트엔드가 같은 프로세스일 때 HTTP를 완전히 건너뜁니다. 서버 렌더링 페이지의 경우, 이는 더 빠른 빌드와 낮은 레이턴시를 의미합니다.

관리 패널 및 콘텐츠 편집

Payload 3.x의 관리 패널은 React로 구축되고 Next.js 애플리케이션의 일부로 제공됩니다. React 컴포넌트로 사용자 정의할 수 있습니다 — UI의 거의 모든 부분을 재정의할 수 있습니다. 블록 기반 리치 텍스트 편집기 (v3의 Lexical 기반)는 강력하고 확장 가능합니다.

Directus의 관리 패널은 독립형 Vue.js 애플리케이션 (Directus Data Studio)입니다. 세련되고, 강한 시각적 설계를 가지고 있으며, 비기술적 사용자는 빠르게 습득하는 경향이 있습니다. Directus의 플로우/자동화 빌더는 Payload의 훅 시스템보다 훨씬 더 시각적이고 접근 가능합니다.

기능 Payload CMS Directus
관리 프레임워크 React (Next.js) Vue.js (독립형)
리치 텍스트 편집기 Lexical 기반 TipTap / WYSIWYG
사용자 정의 필드 React 컴포넌트 Vue 확장
워크플로우/자동화 훅 + 사용자 정의 엔드포인트 Directus 플로우 (시각적 빌더)
지역화 내장 필드 레벨 i18n 내장 필드 레벨 i18n
콘텐츠 버전 관리 초안/게시 + 버전 콘텐츠 버전 관리 + 수정 사항
파일 관리 내장 미디어 라이브러리 변환이 있는 내장 미디어 라이브러리

솔직하게 말하면: 개발자 중심의 팀의 경우, Payload의 관리는 React를 작성하고 있으므로 더 자연스럽게 확장됩니다. 콘텐츠 편집자가 주요 사용자이고 마찰 없는 UX를 원하는 팀의 경우, Directus의 관리 패널은 기본적으로 약간 더 접근하기 쉽습니다.

인증 및 접근 제어

두 시스템 모두 성숙한 인증을 가지고 있지만 다르게 작동합니다.

Payload는 컬렉션 기반 인증을 사용합니다. 컬렉션을 인증 컬렉션 (일반적으로 users)으로 표시하면 로그인, 등록, 비밀번호 재설정, 이메일 확인 및 JWT/쿠키 기반 세션을 받습니다. 접근 제어는 함수를 사용하여 컬렉션별 및 필드별로 정의됩니다:

{
  slug: 'posts',
  access: {
    read: () => true, // 공개
    create: ({ req: { user } }) => Boolean(user), // 인증됨
    update: ({ req: { user } }) => user?.role === 'admin',
    delete: ({ req: { user } }) => user?.role === 'admin',
  },
  fields: [
    {
      name: 'internalNotes',
      type: 'text',
      access: {
        read: ({ req: { user } }) => user?.role === 'admin',
      },
    },
  ],
}

이것은 믿을 수 없을 정도로 강력합니다. 접근 제어 함수는 전체 요청 컨텍스트를 받으므로 RBAC, ABAC, 멀티테넌시, 행 레벨 보안 등의 패턴을 구현할 수 있습니다.

Directus는 관리 패널을 통해 구성된 역할 기반 권한 시스템을 사용합니다. 역할을 생성하고, 세분화된 권한 (컬렉션당 CRUDS)을 할당하며, 필터를 사용하여 사용자 정의 권한을 추가합니다. 시각적이고 직관적이지만 역할 모델에 맞지 않는 복잡한 패턴에는 덜 유연합니다.

대부분의 프로젝트에서 둘 다 충분합니다. 멀티테넌트 SaaS 또는 복잡한 인증 논리의 경우, Payload의 코드 기반 접근 제어는 이기기 어렵습니다.

성능 및 확장성

저는 현실적인 조건 하에서 둘 다 부하 테스트했습니다. PostgreSQL 백엔드를 사용한 관찰은 다음과 같습니다:

메트릭 Payload CMS 3.x Directus 11
간단한 읽기 (단일 항목) ~2-5ms local API, ~15-25ms REST ~15-30ms REST
목록 쿼리 (100개 항목, 관계 없음) ~8-15ms local API, ~30-50ms REST ~25-50ms REST
목록 쿼리 (100개 항목, 2 레벨 깊이) ~20-40ms local API, ~60-100ms REST ~50-120ms REST
콜드 스타트 시간 ~3-6s (Next.js 시작) ~2-4s (독립형)
메모리 기준선 ~200-350MB (Next.js 포함) ~150-250MB

Payload의 Local API 장점은 실제이고 SSR/SSG 워크로드에 상당합니다. 10,000개의 정적 페이지를 생성할 때, 모든 쿼리에 대해 HTTP를 건너뛰면 누적됩니다.

Directus도 성능이 떨어지지 않습니다. 높은 처리량 REST 워크로드를 잘 처리하며, Redis 기반 캐싱 레이어는 성숙합니다.

배포 및 호스팅

Payload 3.x는 Next.js 애플리케이션이므로, Next.js가 실행되는 모든 곳에 배포할 수 있습니다: Vercel, Netlify, AWS, Docker 등. Payload Cloud (관리 호스팅)는 2026년 초 기준으로 프로덕션 프로젝트당 월 $30에서 시작합니다.

Directus는 독립형 Node.js 애플리케이션으로 실행됩니다. Docker가 권장되는 배포 방법입니다. Directus Cloud는 월 $29에서 시작합니다. VPS의 자체 호스팅은 간단합니다 — 데이터베이스 연결이 필요한 Docker 컨테이너일 뿐입니다.

주목할 가치가 있는 것: Payload 3.x가 당신의 Next.js 앱이기 때문에, CMS와 프론트엔드는 함께 배포됩니다. 이것은 인프라를 단순화하지만 CMS 관리 패널은 프론트엔드와 함께 스케일합니다. 프론트엔드와 CMS가 매우 다른 스케일링 필요를 가진 높은 트래픽 사이트의 경우, 이들을 분리하여 실행하는 것을 고려할 수 있습니다.

Directus는 별도의 서비스이므로 자연스럽게 이러한 우려를 분리합니다. 프론트엔드 (Next.js, Astro 또는 다른 것)는 HTTP를 통해 Directus에 연결됩니다. 이것은 더 전통적인 헤드리스 아키텍처입니다.

Social Animal에서 우리는 클라이언트를 위해 두 아키텍처를 모두 배포했습니다. Payload-in-Next.js 접근 방식은 대부분의 마케팅 사이트 및 중규모 애플리케이션에서 아름답게 작동합니다. 여러 프론트엔드 소비자가 있는 엔터프라이즈 설정의 경우, 분리된 Directus 접근 방식이 더 깔끔할 수 있습니다.

2026년 가격 및 라이선싱

Payload CMS Directus
라이선스 MIT GPL-3.0 (클라우드 기능의 BSL 포함)
자체 호스팅 비용 무료 무료
클라우드 호스팅 $30/월부터 (Payload Cloud) $29/월부터 (Directus Cloud)
엔터프라이즈 계층 사용자 정의 가격 사용자 정의 가격 (~$1,500/월부터)
프리미엄 기능 일부 기능 클라우드 전용 Directus+ 구독 (마켓플레이스 확장의 경우 월 $99)

둘 다 자체 호스팅을 위해 정말로 오픈소스입니다. Payload의 MIT 라이선스는 더 허용적입니다 — 제한 없이 상업 제품에 임베드할 수 있습니다. Directus의 GPL-3.0 라이선스는 파생 작업도 GPL이어야 함을 의미하며, 이는 SaaS 제품에 중요할 수 있습니다.

Directus는 2025년 말에 Directus+를 도입했으며, 프리미엄 마켓플레이스 확장 및 우선 지원을 잠금 해제하는 구독입니다. 선택사항이지만 더 고급 확장 (AI 콘텐츠 어시스턴트 같은)은 이 지불 벽 뒤에 있습니다.

어느 것을 선택할 때

다음 경우 Payload CMS를 선택하세요:

  • 처음부터 새 프로젝트를 구축 중입니다 (그린필드)
  • 팀이 TypeScript에 정통하고 스키마를 코드로 원합니다
  • Next.js를 사용 중이고 가장 긴밀한 통합을 원합니다
  • 복잡한 코드 정의 접근 제어가 필요합니다
  • 모든 것을 하나의 배포 가능한 단위로 원합니다
  • MIT 라이선싱을 원합니다

다음 경우 Directus를 선택하세요:

  • 관리해야 할 기존 데이터베이스가 있습니다
  • 팀에 스키마를 수정해야 할 비개발자가 포함되어 있습니다
  • 하나의 CMS에서 여러 프론트엔드 (웹, 모바일, IoT)를 지원해야 합니다
  • 시각적 자동화/플로우 빌더가 필요합니다
  • 광범위한 데이터베이스 지원이 필요합니다 (MySQL, MSSQL, Oracle 등)
  • CMS를 별도의 독립적 서비스로 선호합니다

헤드리스 프로젝트에 대해 이 옵션들의 무게를 재고 있으며 제2의 의견을 원한다면, 우리는 헤드리스 CMS 아키텍처 컨설팅을 하고 있으며 당신이 잘못된 도구로 3개월을 들어가기 전에 올바른 도구를 선택하는 데 도움을 드릴 수 있습니다.

Astro를 프론트엔드 프레임워크로 사용하는 프로젝트의 경우, Directus의 독립형 API 접근 방식은 Astro가 빌드 시간 또는 서버 엔드포인트를 통해 데이터를 가져오므로 자연스럽게 쌍을 이룹니다. Payload도 작동하지만, Astro와 Payload가 별도의 프로세스가 되므로 Local API 장점을 잃습니다.

FAQ

Payload CMS는 정말 2026년에 무료입니까? 예. Payload CMS는 MIT 라이선스이고 완전히 자체 호스팅 가능합니다. Payload Cloud는 관리 호스팅 서비스이지만, CMS 자체 — 모든 핵심 기능 포함 — 오픈소스입니다. 자체 호스팅 버전에는 기능 게이트가 없습니다.

Directus는 기존 데이터베이스를 수정하지 않고 작동할 수 있습니까? 대부분 예. Directus는 기존 데이터베이스를 내재하고 위에 관리 레이어를 생성할 수 있습니다. 자체 구성을 위해 몇 가지 시스템 테이블 (directus_ 접두사)을 추가하지만 기존 테이블을 수정하지 않습니다. 이것은 가장 강한 차별화 중 하나입니다.

단독 개발자에게는 어느 것이 더 좋습니까? Payload CMS는 TypeScript에 편한 단독 개발자들 사이에서 선호하는 경향이 있습니다. 코드 우선 워크플로우는 빠르게 컬렉션을 설정할 수 있으며, 자동 생성된 타입은 보일러플레이트를 줄입니다. Directus는 구성 파일을 작성하지 않고 빠른 스키마 프로토타이핑을 위해 시각적 인터페이스를 원하는 경우에 더 좋습니다.

Next.js 없이 Payload CMS를 사용할 수 있습니까? Payload 3.x의 경우, Next.js가 기본 어댑터이고 관리 패널은 Next.js에서 실행됩니다. 그러나 REST 및 GraphQL API는 모든 프론트엔드와 작동합니다. 소비자 대면 사이트에서 Next.js에 잠기지 않습니다 — Payload 관리를 실행하려면 Next.js만 필요합니다. 추가 어댑터 (Nuxt 같은)에 대한 커뮤니티 논의가 있었지만 공식적인 것은 없습니다.

Directus는 콘텐츠 지역화를 어떻게 처리합니까? Directus는 필드 레벨 번역을 지원합니다. 필드를 번역 가능으로 표시하고, 언어를 구성하면, Directus는 관련 테이블에 번역을 저장하는 것을 처리합니다. API를 통해 ?fields 및 언어 매개변수를 사용하여 특정 언어의 콘텐츠를 요청할 수 있습니다. 잘 구현되어 있으며 수년 동안 안정적입니다.

어느 것이 더 나은 플러그인/확장 지원을 가지고 있습니까? Directus는 더 큰 확장 마켓플레이스를 가지고 있으며, 특히 Directus+ 추가를 사용합니다. 사용자 정의 인터페이스, 디스플레이, 엔드포인트, 훅 및 모듈을 구축할 수 있습니다. Payload의 확장 모델은 React 컴포넌트 재정의 및 플러그인 기반입니다 — 강력하지만 생태계가 더 작습니다. Payload의 플러그인은 더 초점을 맞춘 경향이 있습니다 (SEO 플러그인, 양식 빌더, 리다이렉트) Directus 확장이 더 넓은 범위를 다룹니다.

큰 데이터셋의 경우 성능 차이가 있습니까? 수백만 개의 행이 있는 데이터셋의 경우, 적절히 인덱싱된 둘 다 잘 수행합니다. Directus는 API 쿼리에서 더 직접적으로 SQL을 생성하기 때문에 원시 쿼리 유연성에서 약간의 우위가 있습니다. Payload의 Drizzle ORM 레이어는 효율적이지만 작은 추상화 비용을 추가합니다. 실제로 데이터베이스 튜닝은 어느 CMS를 선택하는지보다 훨씬 더 중요합니다. 둘 다 연결 풀링을 지원하고 읽기 복제본과 작동할 수 있습니다.

나중에 하나에서 다른 것으로 마이그레이션할 수 있습니까? 할 수 있지만 사소하지 않습니다. 콘텐츠 데이터 자체 (둘 다 PostgreSQL에 저장)는 표준 데이터베이스 도구를 사용하여 마이그레이션할 수 있습니다. 더 어려운 부분은 스키마 정의, 접근 제어 규칙 및 모든 사용자 정의 논리를 다시 만드는 것입니다. 헤드리스 아키텍처를 구축하는 경우, CMS 특정 API (추상화 레이어 사용)에서 프론트엔드를 분리하면 향후 CMS 마이그레이션이 크게 더 쉬워질 것입니다.