Content Type

Content Type은 콘텐츠가 따르는 양식(스키마)입니다. 어떤 필드를 가지고, 각 필드가 어떤 타입·다국어 여부·필수 여부·유효성 규칙을 갖는지를 정의합니다. 옷가게 쇼핑몰의 "상품"을 예로 들면, 상품명·가격·상세 설명·대표 사진 같은 항목 구성을 Content Type "상품" 하나가 규정하고, 실제 개별 상품은 이 양식을 따르는 Content로 만들어집니다.

CMA에서 Content TypeSpace 하위 리소스이며, 경로는 /spaces/{spaceId}/content-types를 기준으로 합니다. 생성·수정·발행취소 같은 관리 작업은 CMA에서 수행하고, 발행된 스냅샷은 CDA로 전달됩니다. 단 Content Type은 생성·수정 시 자동으로 발행되므로, Content와 달리 별도 발행 호출 없이도 곧바로 Published 상태가 됩니다(아래 상태와 자동 발행 참조).

리소스 구조

다음은 Content Type "상품"의 단일 조회 응답입니다. sys(시스템 속성)와 함께 name, displayField, publishWithAuthor, fields 같은 본문 속성을 가집니다.

{
  "sys": {
    "id": "3trmXRLdJF4GBlAjtcuoZ7Pnxj8dlA",
    "type": "ContentType",
    "space": { "sys": { "id": "HnQ32YiH", "type": "Refer", "targetType": "Space" } },
    "publish": {
      "version": 7,
      "at": "2026-06-17T03:13:49.973Z",
      "firstAt": "2026-06-14T17:04:46.953Z",
      "counter": 4,
      "by": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } }
    },
    "createdBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
    "createdAt": "2026-06-14T17:04:46.846Z",
    "updatedBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
    "updatedAt": "2026-06-17T03:13:49.973Z",
    "version": 8,
    "status": "Published"
  },
  "name": "상품",
  "displayField": "productName",
  "publishWithAuthor": false,
  "fields": [
    { "id": "5n06s7ocmwdi", "name": "상품명", "apiName": "productName", "type": "ShortText", "localized": true, "required": true, "validations": [], "disabled": false },
    { "id": "1gecyz8g4llwf", "name": "가격", "apiName": "price", "type": "Long", "localized": false, "required": false, "validations": [], "disabled": false },
    { "id": "3ow4popgz54zg", "name": "상세 설명", "apiName": "description", "type": "RichText", "localized": true, "required": false, "validations": [], "disabled": false },
    { "id": "2alxdptmdub1s", "name": "대표 사진", "apiName": "photo", "type": "Refer", "localized": false, "required": false, "validations": [], "disabled": false, "targetType": "Media" },
    {
      "id": "2a80lehazfx3t",
      "name": "브랜드",
      "apiName": "brand",
      "type": "Refer",
      "localized": false,
      "required": false,
      "validations": [
        { "referContentType": [ { "sys": { "id": "3trmXRM3RqbgSnifyg7OveRYWnJWEG", "type": "Refer", "targetType": "ContentType" } } ] }
      ],
      "disabled": false,
      "targetType": "Content"
    }
  ]
}

주요 키:

  • sys.id: Content Type의 고유 식별자입니다. 단일 조회·수정·삭제 경로의 {contentTypeId}에 들어갑니다.
  • name: Content Type의 이름입니다(예: 상품).
  • displayField: 콘텐츠 스튜디오 목록에서 각 Content를 대표해 보여 줄 필드의 apiName입니다(예: productName).
  • publishWithAuthor: Content를 발행할 때 발행 스냅샷에 작성자 정보(sys.createdBy·sys.updatedBy)를 함께 담을지 여부입니다. 기본값은 false이며, 이때 CDA/ACDA로 전달되는 스냅샷에는 작성자가 담기지 않습니다. 이 값은 발행 시점에 적용되고 소급되지 않으므로, 나중에 true로 바꿔도 이미 발행된 Content는 다시 발행해야 작성자가 채워집니다. 관리 API(CMA/ACMA)가 다루는 초안에는 이 설정과 무관하게 sys.createdBy가 있습니다. 전달 응답에 작성자(byline)를 노출하거나 권한 규칙의 createdBy 필터(:self 포함)를 CDA/ACDA에서 판정하려면 이 값을 true로 두어야 합니다(SpaceRole·ServiceUserRolecreatedBy 필터 설명 참고).
  • fields: 이 양식이 정의하는 필드 목록입니다. 각 항목의 구조는 아래 필드에서 설명합니다.

photo 필드는 typeRefer이고 targetTypeMedia이므로 업로드한 파일 자산을 가리킵니다. brand 필드는 Refer + targetType: Content이며, validationsreferContentType로 특정 Content Type(여기서는 "브랜드")의 Content만 참조하도록 제한합니다.

시스템 속성 (sys)

모든 Content Type은 공통 시스템 속성과 Content Type 고유 속성을 sys 객체에 담습니다. space, createdBy, updatedByRefer 모양({ "sys": { "id", "type": "Refer", "targetType" } })으로 들어갑니다.

속성타입설명
idstring리소스 고유 식별자.
typestring리소스 종류. Content Type은 항상 "ContentType".
spaceRefer<Space>Content Type이 속한 Space.
createdByRefer<User>생성한 사용자.
createdAtstring (date-time)생성 시각.
updatedByRefer<User>마지막으로 수정한 사용자.
updatedAtstring (date-time)마지막 수정 시각.
versioninteger (≥1)리소스 버전. 생성·수정·발행·발행취소 등 모든 변경마다 1씩 올라갑니다.
statusstring (enum)발행 상태. Draft, Changed, Published, Archived 중 하나.
publishobject발행 이력. 아래 키 참조.

publish 객체의 키:

타입설명
versioninteger마지막으로 발행된 시점의 sys.version.
atstring (date-time)마지막 발행 시각.
firstAtstring (date-time)최초 발행 시각. 발행취소해도 보존됩니다.
counterinteger누적 발행 횟수.
byRefer<User>마지막으로 발행한 사용자.

발행취소(DELETE .../publish)하면 publish에서 version, at, by가 제거되고 firstAt, counter만 남습니다.

Content Typesys에는 Contentsys에 있는 contentType(자기 참조) 속성이 없습니다. Content Type 자체가 양식이기 때문입니다. archive 속성도 없습니다.

필드

fields는 이 Content Type이 정의하는 필드의 목록입니다. 각 항목은 다음 구조(FieldDefinition)를 가집니다.

타입설명
idstring (1~64)필드의 고유 식별자. 생성 시 자동 부여됩니다.
namestring (1~50)콘텐츠 스튜디오에 표시되는 필드 이름(예: 상품명).
apiNamestring (1~64)API에서 이 필드를 가리키는 키. 패턴 ^[a-zA-Z0-9][a-zA-Z0-9-_]*$(영문·숫자로 시작, 이후 영문·숫자·-·_).
typestring (enum)필드의 타입. 아래 필드 종류 (type) 참조.
localizedboolean다국어 값을 가질 수 있는지 여부.
requiredboolean필수 입력 여부.
validationsarray값에 적용할 유효성 규칙 목록. 규칙이 없으면 빈 배열 []. 아래 유효성 검사 (validations) 참조.
disabledboolean비활성화 여부.
targetTypestring (enum)typeRefer일 때만. 참조 대상이 Content인지 Media인지.
itemsobjecttypeArray일 때만. 배열 원소의 정의(Refer 원소 또는 ShortText 원소).

필드 종류 (type)

type은 값이 저장·조회되는 방식을 결정합니다. 일부 타입은 검색 동작이 다릅니다.

type의미값 제한비고
ShortText짧은 단일 줄 텍스트.64자정확 키워드 조회에 적합.
LongText긴 본문 텍스트.5,120자전문(full-text) 유사도 검색을 지원.
RichText서식이 있는 본문.204,800자검색 대상이 아니며 서식 표현용.
Long정수.예: 가격 price.
Number실수(소수 포함).유한한 값만무한대와 NaN은 받지 않습니다.
Boolean참/거짓.
Date날짜·시각.
Json임의 JSON 구조.직렬화 5,120자구조 안의 숫자도 유한해야 합니다.
Location위치(좌표).latitude -9090, longitude -180180
Refer다른 리소스를 가리키는 참조.targetType으로 Content 또는 Media를 지정.
Array여러 값을 담는 배열.원소 64개items로 원소 정의를 동반.

"상품" 예시에서 상품명ShortText, 가격Long, 상세 설명RichText, 대표 사진Refer(targetType: Media), 브랜드Refer(targetType: Content)입니다.

값 제한은 타입이 정하는 플랫폼 상한이며, Content Type을 만들 때가 아니라 Content에 값을 쓸 때 검사합니다. validationssize로 이보다 큰 상한을 적어도 플랫폼 상한이 먼저 걸립니다. Array의 원소에는 원소 타입의 같은 제한이 그대로 적용되므로, items.typeShortText인 배열은 원소 하나하나가 64자를 넘을 수 없습니다. 제한을 넘긴 값으로 Content를 쓰면 거부되며, 그 코드는 Content의 오류에 있습니다.

유효성 검사 (validations)

validations는 필드 값에 적용할 규칙의 배열입니다. 각 항목은 다음 키 중 하나를 담습니다.

형태설명
size{ "min", "max" }텍스트 길이 또는 배열 크기의 최소·최대.
uniqueboolean같은 Content Type 안에서 값의 중복을 금지.
regexp{ "pattern", "flags" }값이 정규식 패턴과 일치해야 함. pattern 필수.
prohibitRegexp{ "pattern", "flags" }값이 정규식 패턴과 일치하면 거부. pattern 필수.
inarray허용 값 목록. 목록에 있는 값만 통과.
range{ "min", "max" }숫자 값의 최소·최대.
dateRange{ "min", "max", "after", "before" }날짜 값의 허용 범위.
mediaMimetypeGrouparrayRefer(Media) 필드에서 허용할 파일 유형 목록. 아래 enum 참조.
mediaImageDimensions{ "width", "height" }이미지의 가로·세로 픽셀 제약.
mediaFileSize{ "min", "max" }파일 크기(바이트)의 최소·최대.
referContentTypearrayRefer(Content) 필드에서 참조를 허용할 Content Type 목록. 각 항목은 Refer<ContentType> 모양.
messagestring검증 실패 시 표시할 사용자 정의 메시지.

mediaMimetypeGroup에 쓸 수 있는 값(12종): Attachment, Plaintext, Image, Audio, Video, RichText, Presentation, Spreadsheet, PdfDocument, Archive, Code, Markup.

"상품" 예시의 brand 필드는 referContentType로 "브랜드" Content Type(sys.id3trmXRM3RqbgSnifyg7OveRYWnJWEG)만 참조하도록 제한합니다.

상태와 자동 발행

Content Type생성·수정·부분 수정 시 자동으로 발행됩니다. 이 점이 Content와 다릅니다. Content는 생성 후 별도의 발행 호출이 있어야 전달 경로에 오르지만, Content Type은 생성 응답이 곧바로 status: "Published"로 돌아옵니다.

status는 다음 4가지 중 하나입니다.

status의미
Draft발행되지 않은 상태.
Changed발행된 적이 있으나 이후 변경분이 아직 발행되지 않은 상태.
Published발행되어 있고 미발행 변경분이 없는 상태.
Archived보관된 상태.

sys.version은 모든 변경에서 1씩 증가합니다. Content Type은 수정과 발행이 한 번에 일어나므로, 수정 한 번이 version을 2 올립니다(수정 자체 +1, 자동 발행 +1). 예시 "공지사항"에서 생성 직후 version은 2(생성 +1, 자동 발행 +1)이고 publish.counter는 1입니다. 이어 수정하면 version은 4가 되고 publish.counter는 2가 됩니다.

Content TypeDraft가 되는 유일한 경로는 명시적 발행취소(DELETE .../publish)입니다. 발행취소하면 statusDraft가 되고, publish 객체에서 version·at·by가 빠진 채 firstAt·counter만 남습니다.

제약

대상제약
name(Content Type)1~64자, 필수.
description128자 이하, 선택.
fields1~80개. 생성·수정·부분 수정 모두 이 범위를 지켜야 합니다.
name(필드)1~50자, 필수.
apiName(필드)1~64자, 패턴 ^[a-zA-Z0-9][a-zA-Z0-9-_]*$, 필수.

삭제 가드: 삭제는 두 조건을 모두 만족해야 합니다.

  • Content Type을 쓰는 Content가 하나라도 있으면 삭제할 수 없습니다. 먼저 해당 Content를 모두 삭제하세요. 이 검사가 가장 먼저 걸립니다.
  • 발행 상태(Published·Changed)인 Content Type은 바로 삭제할 수 없습니다. 먼저 발행취소(DELETE .../publish)해 Draft로 만든 뒤 삭제하세요(Archived 상태도 삭제 가능).

오류

Content Type을 다룰 때 만나는 코드입니다. 모든 리소스에 공통인 코드는 공통 오류를 참조하세요.

코드조건
WGL422010Content Type을 쓰는 Content가 아직 남아 있는데 Content Type을 삭제하려 했습니다. 발행취소도 같은 검사를 받으므로, Content가 남아 있으면 발행취소부터 이 코드로 거부됩니다.
WGL422009발행 상태(Published·Changed)인 Content Type을 발행취소하지 않고 삭제하려 했습니다.
WGL422006발행 상태가 아닌 Content Type을 발행취소하려 했습니다.
WGL400002fields가 허용 개수를 넘습니다. 생성·수정·부분 수정 모두 이 검사를 받습니다.
WGL400045displayField에 적은 값이 그 Content TypefieldsapiName 중 어디에도 없습니다.
WGL400046짝이 되는 속성을 함께 적어야 하는 필드에 그 속성이 없습니다. Array에는 items, Refer에는 targetType이 필요합니다.
WGL400040같은 apiName을 가진 필드가 둘 이상입니다.

API

아래 모든 엔드포인트의 기준 URL은 https://cma.weegloo.com/v1이며, Authorization 헤더에 CMA를 인증하는 Bearer 토큰이 필요합니다. 수정·부분 수정·발행·발행취소는 낙관적 동시성 제어를 위해 X-Weegloo-Version 헤더(현재 리소스의 sys.version)를 함께 보내야 합니다.