Content Type
최종 수정: 2026년 7월 3일
Content Type은 콘텐츠가 따르는 틀(스키마)입니다. 어떤 필드를 가지고, 각 필드가 어떤 타입·다국어 여부·필수 여부·유효성 규칙을 갖는지를 정의합니다. 옷가게 쇼핑몰의 "상품"을 예로 들면, 상품명·가격·상세 설명·대표 사진 같은 항목 구성을 Content Type "상품" 하나가 규정하고, 실제 개별 상품은 이 틀을 따르는 Content로 만들어집니다.
CMA에서 Content Type은 Space 하위 리소스이며, 경로는 /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 발행 시 작성자 정보를 함께 담을지 여부입니다. 기본값은false입니다.fields: 이 틀이 정의하는 필드 목록입니다. 각 항목의 구조는 아래 필드에서 설명합니다.
photo 필드는 type이 Refer이고 targetType이 Media이므로 업로드한 파일 자산을 가리킵니다. brand 필드는 Refer + targetType: Content이며, validations의 referContentType로 특정 Content Type(여기서는 "브랜드")의 Content만 참조하도록 제한합니다.
시스템 속성 (sys)
모든 Content Type은 공통 시스템 속성과 Content Type 고유 속성을 sys 객체에 담습니다. space, createdBy, updatedBy는 Refer 모양({ "sys": { "id", "type": "Refer", "targetType" } })으로 들어갑니다.
| 속성 | 타입 | 설명 |
|---|---|---|
id | string | 리소스 고유 식별자. |
type | string | 리소스 종류. Content Type은 항상 "ContentType". |
space | Refer<Space> | 이 Content Type이 속한 Space. |
createdBy | Refer<User> | 생성한 사용자. |
createdAt | string (date-time) | 생성 시각. |
updatedBy | Refer<User> | 마지막으로 수정한 사용자. |
updatedAt | string (date-time) | 마지막 수정 시각. |
version | integer (≥1) | 리소스 버전. 생성·수정·발행·발행취소 등 모든 변경마다 1씩 올라갑니다. |
status | string (enum) | 발행 상태. Draft, Changed, Published, Archived 중 하나. |
publish | object | 발행 이력. 아래 키 참조. |
publish 객체의 키:
| 키 | 타입 | 설명 |
|---|---|---|
version | integer | 마지막으로 발행된 시점의 sys.version. |
at | string (date-time) | 마지막 발행 시각. |
firstAt | string (date-time) | 최초 발행 시각. 발행취소해도 보존됩니다. |
counter | integer | 누적 발행 횟수. |
by | Refer<User> | 마지막으로 발행한 사용자. |
발행취소(DELETE .../publish)하면 publish에서 version, at, by가 제거되고 firstAt, counter만 남습니다.
Content Type의 sys에는 Content의 sys에 있는 contentType(자기 참조) 속성이 없습니다. Content Type 자체가 틀이기 때문입니다. archive 속성도 없습니다.
필드
fields는 이 Content Type이 정의하는 필드의 목록입니다. 각 항목은 다음 구조(FieldDefinition)를 가집니다.
| 키 | 타입 | 설명 |
|---|---|---|
id | string (1~64) | 필드의 고유 식별자. 생성 시 자동 부여됩니다. |
name | string (1~50) | 콘텐츠 스튜디오에 표시되는 필드 이름(예: 상품명). |
apiName | string (1~64) | API에서 이 필드를 가리키는 키. 패턴 ^[a-zA-Z0-9][a-zA-Z0-9-_]*$(영문·숫자로 시작, 이후 영문·숫자·-·_). |
type | string (enum) | 필드의 타입. 아래 필드 종류 (type) 참조. |
localized | boolean | 다국어 값을 가질 수 있는지 여부. |
required | boolean | 필수 입력 여부. |
validations | array | 값에 적용할 유효성 규칙 목록. 규칙이 없으면 빈 배열 []. 아래 유효성 검사 (validations) 참조. |
disabled | boolean | 비활성화 여부. |
targetType | string (enum) | type이 Refer일 때만. 참조 대상이 Content인지 Media인지. |
items | object | type이 Array일 때만. 배열 원소의 정의(Refer 원소 또는 ShortText 원소). |
필드 종류 (type)
type은 값이 저장·조회되는 방식을 결정합니다. 일부 타입은 검색 동작이 다릅니다.
type | 의미 | 비고 |
|---|---|---|
ShortText | 짧은 단일 줄 텍스트. | 정확 키워드 조회에 적합. |
LongText | 긴 본문 텍스트. | 전문(full-text) 유사도 검색을 지원. |
RichText | 서식이 있는 본문. | 검색 대상이 아니며 서식 표현용. |
Long | 정수. | 예: 가격 price. |
Number | 실수(소수 포함). | |
Boolean | 참/거짓. | |
Date | 날짜·시각. | |
Json | 임의 JSON 구조. | |
Location | 위치(좌표). | |
Refer | 다른 리소스를 가리키는 참조. | targetType으로 Content 또는 Media를 지정. |
Array | 여러 값을 담는 배열. | items로 원소 정의를 동반. |
"상품" 예시에서 상품명은 ShortText, 가격은 Long, 상세 설명은 RichText, 대표 사진은 Refer(targetType: Media), 브랜드는 Refer(targetType: Content)입니다.
유효성 검사 (validations)
validations는 필드 값에 적용할 규칙의 배열입니다. 각 항목은 다음 키 중 하나를 담습니다.
| 키 | 형태 | 설명 |
|---|---|---|
size | { "min", "max" } | 텍스트 길이 또는 배열 크기의 최소·최대. |
unique | boolean | 같은 Content Type 안에서 값의 중복을 금지. |
regexp | { "pattern", "flags" } | 값이 정규식 패턴과 일치해야 함. pattern 필수. |
prohibitRegexp | { "pattern", "flags" } | 값이 정규식 패턴과 일치하면 거부. pattern 필수. |
in | array | 허용 값 목록. 목록에 있는 값만 통과. |
range | { "min", "max" } | 숫자 값의 최소·최대. |
dateRange | { "min", "max", "after", "before" } | 날짜 값의 허용 범위. |
mediaMimetypeGroup | array | Refer(Media) 필드에서 허용할 파일 유형 목록. 아래 enum 참조. |
mediaImageDimensions | { "width", "height" } | 이미지의 가로·세로 픽셀 제약. |
mediaFileSize | { "min", "max" } | 파일 크기(바이트)의 최소·최대. |
referContentType | array | Refer(Content) 필드에서 참조를 허용할 Content Type 목록. 각 항목은 Refer<ContentType> 모양. |
message | string | 검증 실패 시 표시할 사용자 정의 메시지. |
mediaMimetypeGroup에 쓸 수 있는 값(12종): Attachment, Plaintext, Image, Audio, Video, RichText, Presentation, Spreadsheet, PdfDocument, Archive, Code, Markup.
"상품" 예시의 brand 필드는 referContentType로 "브랜드" Content Type(sys.id가 3trmXRM3RqbgSnifyg7OveRYWnJWEG)만 참조하도록 제한합니다.
상태와 자동 발행
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 Type이 Draft가 되는 유일한 경로는 명시적 발행취소(DELETE .../publish)입니다. 발행취소하면 status가 Draft가 되고, publish 객체에서 version·at·by가 빠진 채 firstAt·counter만 남습니다.
제약
| 대상 | 제약 |
|---|---|
name(Content Type) | 1~64자, 필수. |
description | 128자 이하, 선택. |
fields | 생성 시 1~80개, 수정 시 최소 1개. |
name(필드) | 1~50자, 필수. |
apiName(필드) | 1~64자, 패턴 ^[a-zA-Z0-9][a-zA-Z0-9-_]*$, 필수. |
삭제 가드: 삭제는 두 조건을 모두 만족해야 합니다.
- 이 Content Type을 쓰는 Content가 하나라도 있으면 삭제할 수 없습니다(
WGL422010). 먼저 해당 Content를 모두 삭제하세요. 이 검사가 가장 먼저 걸립니다. - 발행 상태(
Published·Changed)인 Content Type은 바로 삭제할 수 없습니다(WGL422009). 먼저 발행취소(DELETE .../publish)해Draft로 만든 뒤 삭제하세요(Archived상태도 삭제 가능).
API
아래 모든 엔드포인트의 기준 URL은 https://cma.weegloo.com/v1이며, Authorization 헤더에 CMA를 인증하는 Bearer 토큰이 필요합니다. 수정·부분 수정·발행·발행취소는 낙관적 동시성 제어를 위해 X-Weegloo-Version 헤더(현재 리소스의 sys.version)를 함께 보내야 합니다.
관련 문서
- Content 모델링: Content Type을 콘텐츠 스튜디오에서 만드는 법.
- 상태와 발행: 발행·버전의 의미.
