콘텐츠로 이동

콘텐츠 관리

Proyecta의 CMS는 앱의 기본 데이터 레이어입니다 — 블로그 게시물이나 마케팅 문구만을 위한 것이 아니라, 앱의 근간이 되는 실제 레코드를 담습니다. 컬렉션은 UI가 존재하기 전에 프로비저닝되고 실제 샘플 콘텐츠로 시딩되므로, 첫 번째 빌드부터 편집 가능한 데이터에 연결된 상태로 앱이 출시됩니다.

대부분의 Proyecta 앱은 내장 CMS에 데이터를 저장합니다. 앱을 설명하면 Proyecta가 데이터 모델을 설계하고, 필요한 컬렉션을 생성하고, 현실적인 샘플 콘텐츠로 채웁니다 — 이 모든 것이 단 하나의 페이지가 만들어지기 전에 이루어집니다. 그런 다음 페이지들은 AI가 자동으로 연결해 주는 타입이 지정된 hook을 통해 실제의 편집 가능한 콘텐츠를 읽습니다. 이 모든 것이 어떻게 맞물리는지 큰 그림을 보려면 **앱 데이터 작동 방식**을 참조하세요.

시작하는 데 이런 내용을 일일이 알 필요는 없습니다 — 모두 자동으로 처리됩니다. 이 페이지는 그 내부 구조를 이해하고 직접 조정할 수 있도록 설명합니다.

콘텐츠는 컬렉션싱글톤으로 구성됩니다:

타입 설명 예시
Collection 여러 항목을 가진 콘텐츠 타입 — 하나의 스키마, 여러 행. posts, services, testimonials, catalogItems
Singleton 정확히 하나의 항목만 가진 콘텐츠 타입 — 전역적, 단일 콘텐츠. businessInfo, seoSettings

컬렉션은 하나의 _형태_이고, 각 항목은 그 형태의 단일 아이템입니다 (블로그 게시물 하나, 서비스 하나, FAQ 하나). 싱글톤은 단일 편집 가능 레코드를 담습니다 — 비즈니스 정보나 페이지의 히어로/섹션 문구 등이 이에 해당합니다.

어떤 종류의 콘텐츠를 다루나요

섹션 제목: “어떤 종류의 콘텐츠를 다루나요”

Proyecta는 실제 비즈니스가 관리하는 레코드 유형에 맞춘 완성된 컬렉션 디자인을 기본 제공합니다 — 합리적인 필드 구성, 관리자 힌트, 스타터 콘텐츠를 포함하여 블로그 게시물 및 아티클, 서비스, 상품 카탈로그, 음식 메뉴, 후기 및 리뷰, 팀 멤버, 사진 갤러리, FAQ, 이벤트, 지점 위치, 다운로드 가능 리소스, 채용 공고, 강좌, 투어, 숙박 시설 목록 등 다양한 유형을 지원합니다.

목록에서 직접 선택할 필요가 없습니다. 앱을 설명하면 Proyecta가 비즈니스 유형, 요청한 기능, 언어 등 브리프에 맞는 컬렉션을 선택하고, 현실적인 샘플 콘텐츠로 미리 채워 생성합니다. 기존 컬렉션 중 어느 것도 앱에 맞지 않는다면, Proyecta가 고유한 필드를 가진 커스텀 컬렉션을 직접 설계합니다.

그렇기 때문에 관리자 패널에는 고정된 목록이 아닌 앱의 컬렉션이 표시됩니다. 관리자 패널은 앱의 라이브 콘텐츠 모델을 기반으로 스스로 구성되므로, Proyecta가 생성한 것이 기본 제공이든 커스텀이든 관계없이 보이는 것과 편집하는 것이 완전히 일치합니다. 두 Proyecta 앱이 동일한 컬렉션 세트를 가지는 경우는 거의 없으며, 이는 의도된 설계입니다.

모든 컬렉션은 타입이 지정된 필드로 구성됩니다. 필드 타입은 전 구간에서 적용됩니다 — 관리자 패널은 적절한 에디터를 렌더링하고, 페이지는 올바르게 타입이 지정된 값을 받습니다.

필드 타입 사용 목적
string 짧은 한 줄 값 — 제목, 이름, 주소.
text 일반 텍스트 단락.
markdown 긴 형식의 서식 있는 텍스트 — 아티클 본문, “소개” 문구.
slug URL 식별자, 다른 필드(예: 제목)에서 자동으로 파생됨.
number 수량, 평점, 기간.
money 가격 또는 통화 금액 — 금액으로 표시 및 편집됨.
boolean 켜기/끄기 플래그.
date 날짜.
datetime 타임스탬프 — 게시 날짜, 이벤트 시작 시간.
weeklyHours 요일별 영업 시간.
asset 이미지, 동영상, 또는 PDF (공개 URL로 저장됨).
reference 다른 컬렉션의 항목에 대한 링크.
enum 고정된 선택지 목록에서 선택한 값.
array 문자열 목록 — 태그, 전화번호, 구역.
blocks 쌓을 수 있는 콘텐츠 블록 — 타입이 지정된 섹션으로 구성된 페이지.
json 위의 타입 중 어느 것도 맞지 않는 구조화된 데이터.

**항목(entry)**은 컬렉션 내의 단일 아이템입니다. 모든 항목에는 상태가 있습니다:

  • Draft — 작업 중인 내용으로, 라이브 사이트에 절대 표시되지 않습니다.
  • Published — 라이브 상태로 방문자에게 보입니다.
  • Archived — 사용 중단된 상태로, 별도로 보관됩니다.

공개 페이지는 게시된(published) 항목만 볼 수 있습니다 — 초안 및 보관된 항목은 자동으로 숨겨지므로, 콘텐츠가 공개되기 전에 안전하게 준비할 수 있습니다.

콘텐츠를 추가하고 편집하는 방법은 두 가지이며, 둘 다 코드를 다룰 필요가 없습니다:

  1. 채팅에서 AI에게 요청. 변경 사항을 설명하면 AI가 올바른 콘텐츠를 직접 편집해 줍니다:
    • "María González의 후기를 추가해줘: '동네 최고의 서비스', 별점 5점."
    • "Business Info의 태그라인을 'Café de especialidad en la Roma'로 바꿔줘."
    • "마지막 다섯 개의 문의 양식 제출 항목을 읽음으로 표시해줘."
  2. 앱의 관리자 패널. 게시된 모든 앱에는 로그인으로 보호되는 내장 **관리자 패널**이 제공되며, 여기서 본인(및 접근 권한을 부여한 직원)이 콘텐츠와 양식 제출물을 직접 관리할 수 있습니다 — 컬렉션별 스프레드시트 스타일 에디터와 제출물 받은 편지함이 포함됩니다. 관리자 패널은 앱의 라이브 콘텐츠 모델을 기반으로 스스로 구성되므로, 새 컬렉션이 추가되면 자동으로 표시됩니다. **관리자 패널**을 참조하세요.

CMS 콘텐츠는 앱의 관리자 패널 또는 AI를 통해 관리하세요 — 빌더 내 콘텐츠 에디터는 로드맵에 있습니다(곧 출시 예정 참조). 라이브 업데이트 앱을 위한 실시간 레코드 브라우저도 곧 출시 예정입니다.

페이지는 @/hooks/useContent의 타입이 지정된 hook 세트를 통해 콘텐츠를 읽으며, AI가 이 연결 작업을 대신 작성해 줍니다. 페이지를 설명하면 Proyecta가 실제 컬렉션을 대상으로 이 hook을 호출하는 컴포넌트를 생성합니다. 직접 작성할 일은 거의 없지만, 각 hook이 하는 일은 다음과 같습니다:

Hook 기능
useCollection('posts') 컬렉션의 게시된 항목을 나열합니다 (선택적 필터/정렬/제한 적용 가능).
useEntry('posts', slug) slug로 게시된 단일 항목을 가져옵니다 (상세 페이지).
useSingleton('businessInfo') 싱글톤을 읽습니다 (비즈니스 정보, 페이지 콘텐츠).
useFormSubmit('contactForm') 양식을 제출하고 유효성 검사 오류를 보고합니다.
// A blog index — exactly the kind of code the AI generates for you
import { useCollection } from '@/hooks/useContent';
function BlogList() {
const { data: posts, isLoading } = useCollection('posts', { sort: 'published_at:desc' });
if (isLoading) return <Spinner />;
return posts?.map((post) => <PostCard key={post._id} post={post} />);
}

Proyecta가 컬렉션에 대한 타입 인터페이스를 생성하면, hook은 완전히 타입이 지정됩니다 (useCollection<Post>('posts')). 덕분에 에디터에서 모든 필드를 자동 완성할 수 있습니다. 읽기는 미리 구운 스냅샷을 통해 첫 번째 페인트에서 hydrate됩니다 — 페이지가 즉시 렌더링되고 SEO에 친화적이며, 이후 백그라운드에서 실시간으로 새로 고침됩니다.

양식은 AI가 직접 손으로 만드는 것이 아닌 일급(first-class) 기능입니다. 양식 블록을 추가하면 필드를 렌더링하고, 입력값을 유효성 검사하고, 제출하고, 성공 상태를 표시합니다:

<FormBlock form="contactForm" />

양식도 기본 제공됩니다 — 문의 양식, 견적 요청, 예약 양식, 주문 양식, 등록 양식 등 — Proyecta가 페이지에 적합한 양식을 자동으로 연결합니다. 제출물은 앱의 관리자 패널 받은 편지함에 쌓이며, 새 제출물이 도착하면 소유자에게 이메일이 발송됩니다. 자세한 내용은 **양식**을 참조하세요.

콘텐츠는 여러 로케일로 번역될 수 있습니다. 현지화로 표시된 필드는 언어별로 값을 저장하며, 읽기 hook은 방문자의 활성 로케일을 전달할 때 대체 체인(요청 언어 → 설정된 대체 언어 → 기본값)을 통해 값을 반환합니다:

const { data: posts } = useCollection('posts', { locale: 'es' });

단일 언어 앱은 로케일을 완전히 무시합니다 — 별도로 설정할 것이 없습니다. 번역에 관한 더 넓은 이야기는 **국제화**를 참조하세요.

릴리스는 여러 항목을 묶어 한꺼번에 게시(또는 게시 취소)할 수 있게 해줍니다 — 론치, 새 제품 페이지, FAQ 업데이트 등 조율된 콘텐츠 배포를 준비한 뒤 한 번에 전환할 수 있습니다.

참고: 자동 예약 게시는 아직 구현되지 않았습니다. scheduled_at 날짜가 있는 릴리스는 scheduled 상태로 진입하지만 수동으로 게시해야 합니다. 예약된 시간에 자동 게시되는 기능은 곧 출시될 예정입니다.

일반적인 패턴 (AI에게 연결을 맡기세요)

섹션 제목: “일반적인 패턴 (AI에게 연결을 맡기세요)”

직접 코드를 작성할 일은 거의 없습니다 — 원하는 것을 설명하면 Proyecta가 실제 컬렉션을 기반으로 구축해 줍니다:

  • "블로그를 만들어줘. 각 게시물에는 제목, 커버 이미지, 리치 텍스트 본문, 카테고리, 태그가 있어. 공개 경로는 /blog와 /blog/[slug]이고, 최신 순으로 정렬해줘."
  • "소유자가 편집할 수 있는 FAQ 섹션을 카테고리별로 그룹화해서 추가해줘."
  • "예약 가능한 서비스 목록과 견적 요청 양식을 추가해줘."
  • "사이트를 영어와 스페인어 이중 언어로 만들고 언어 전환 버튼을 추가해줘."
  • "커피숍을 위한 현실적인 리뷰 5개로 testimonials를 시딩해줘."

CMS는 지속적인 콘텐츠와 레코드의 기본 저장소입니다. 일부 데이터 종류는 목적에 맞게 별도의 시스템에 저장됩니다:

데이터 종류 저장 위치
콘텐츠 및 레코드 (게시물, 서비스, 목록, FAQ, 카탈로그, 예약) Proyecta CMS (이 페이지) — 기본값
실시간 / 행동 상태 (라이브 채팅, 피드, 접속 상태, 게임 상태) 실시간 저장소곧 출시 예정
사용자 계정 및 로그인 Auth
상품, 주문, 구독, 결제 Commerce
업로드된 파일 및 미디어 Files & Media
빌드에 포함된 정적 에셋 프로젝트의 public/ 디렉토리

CMS가 기본값입니다. 진정한 실시간 동작을 위한 실시간 저장소는 곧 출시 예정이며, 그때에도 지속적인 콘텐츠와 커머스 카탈로그는 CMS에 계속 저장됩니다.

  • 빌더 내 콘텐츠 에디터 — 빌더 대시보드에서 직접 CMS 컬렉션을 탐색하고 편집 (현재는 관리자 패널 또는 AI를 통해 콘텐츠 관리).
  • 리치 텍스트 WYSIWYG 에디터markdown 필드의 시각적 편집 (현재는 마크다운으로 편집됨).
  • 예약 자동 게시 — 예약된 시간에 자동으로 게시되는 릴리스.
  • 콘텐츠 변경 사항의 라이브 미리보기.
  • 콘텐츠 역할 — 에디터 권한과 개발자 권한 분리.