Web Hosting
Web Hosting은 빌드한 정적 웹사이트를 Space에 올려 {subdomain}.weegloo.app 주소로 서비스하는 리소스입니다. 옷가게 쇼핑몰을 예로 들면, 빌드한 쇼핑몰 사이트를 dailywear-shop.weegloo.app으로 띄우는 것이 Web Hosting 한 건입니다.
올리는 순서는 다음과 같습니다. 먼저 빌드 결과를 ZIP 또는 tar.gz로 묶어 Upload API로 올려 Upload 하나를 받습니다. 그 Upload를 참조해 POST /web-hostings로 Web Hosting을 만듭니다. 시스템이 올린 파일을 처리해 sys.state가 COMPLETED가 되면 url로 사이트에 접속할 수 있습니다. CMA에서 Web Hosting은 Space 하위 리소스이며, 경로는 /spaces/{spaceId}/web-hostings를 기준으로 합니다.
리소스 구조
다음은 처리가 끝난 Web Hosting "데일리웨어 쇼핑몰 사이트"의 단일 조회 응답입니다. sys(시스템 속성)와 함께 본문 속성(name·description·isSpa·subdomain·url·pageMetas)을 가집니다.
{
"sys": {
"id": "3trmXRM3RqbgSnifyg7PWeb01Examp",
"type": "WebHosting",
"space": { "sys": { "id": "HnQ32YiH", "type": "Refer", "targetType": "Space" } },
"createdBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
"updatedBy": { "sys": { "id": "3p4tcFbQRwz503VXdtHXNI5dZH5TVB", "type": "Refer", "targetType": "User" } },
"createdAt": "2026-06-18T11:40:00.000Z",
"updatedAt": "2026-06-18T11:40:05.000Z",
"state": "COMPLETED",
"totalFileSize": 245786,
"originMetas": [
{
"file": "index.html",
"meta": {
"title": "Daily Wear Store",
"description": "Everyday clothing store"
}
}
],
"version": 3
},
"name": "데일리웨어 쇼핑몰 사이트",
"description": "옷·잡화 쇼핑몰 정적 사이트",
"isSpa": true,
"subdomain": "dailywear-shop",
"url": "https://dailywear-shop.weegloo.app",
"pageMetas": [
{
"file": "index.html",
"meta": {
"title": "데일리웨어 - 매일 입는 옷",
"description": "출근길에도 주말에도 입는 데일리 의류를 모았습니다.",
"image": "https://dailywear-shop.weegloo.app/og-cover.png"
}
}
]
}주요 키:
subdomain: 사이트가 서비스될 서브도메인입니다. 위 예시는dailywear-shop이며, 최종 주소는dailywear-shop.weegloo.app이 됩니다.url: 처리가 끝난 뒤 접속할 수 있는 사이트 주소입니다.isSpa: 단일 페이지 앱(SPA) 여부입니다.true면 모든 경로 요청을index.html로 보냅니다.state: 올린 파일의 배포 처리 상태입니다. 아래 시스템 속성 (sys)에서 설명합니다.pageMetas: 문서별로 덮어쓴 메타 태그 값입니다.sys.originMetas는 덮어쓰기 전 원래 값입니다. 둘 다 아래 문서별 메타데이터에서 설명합니다.
시스템 속성 (sys)
모든 Web Hosting은 공통 시스템 속성을 sys 객체에 담습니다. space·createdBy·updatedBy는 Refer 모양({ "sys": { "id", "type": "Refer", "targetType" } })으로 들어갑니다.
| 속성 | 타입 | 설명 |
|---|---|---|
id | string | 리소스 고유 식별자. 단일 조회·수정·삭제 경로의 {webHostingId}에 들어갑니다. |
type | string | 리소스 종류. Web Hosting은 항상 "WebHosting". |
space | Refer<Space> | 이 Web Hosting이 속한 Space. |
createdBy | Refer<User> | 생성한 사용자. |
createdAt | string (date-time) | 생성 시각. |
updatedBy | Refer<User> | 마지막으로 수정한 사용자. |
updatedAt | string (date-time) | 마지막 수정 시각. |
state | string (enum) | 배포 처리 상태. 아래 4가지 중 하나. |
error | string | 처리 실패 시 그 사유. 실패가 아니면 비어 있습니다. |
totalFileSize | integer | 올린 파일의 총 크기(바이트). |
originMetas | PageMeta[] | 문서가 원래 갖고 있던 메타 태그 값. MarketApp 설치로 만들어진 Web Hosting에만 채워집니다. 아래 문서별 메타데이터에서 설명합니다. |
version | integer (≥1) | 리소스 버전. 생성·수정마다 1씩 올라갑니다. 수정·부분 수정 요청에 x-weegloo-version으로 실어야 하는 값입니다. |
state는 올린 파일을 배포하는 처리 단계를 나타냅니다. Content의 발행 상태가 아니며, Web Hosting에는 발행이나 보관 개념이 없습니다. 파일을 처리해 COMPLETED가 되면 url로 사이트에 접속됩니다.
state | 의미 |
|---|---|
PENDING | 처리 대기 중. |
PROCESSING | 처리 중. |
COMPLETED | 처리 완료. url로 접속 가능합니다. |
FAILED | 처리 실패. 사유는 sys.error에 담깁니다. |
본문 속성
Web Hosting의 본문 속성은 다음과 같습니다.
| 속성 | 타입 | 설명 |
|---|---|---|
name | string (1~64) | Web Hosting 이름. 생성 시 필수. |
description | string (≤128) | 설명. 선택. |
isSpa | boolean | 단일 페이지 앱 여부. true면 모든 경로 요청을 index.html로 보냅니다(SPA 라우팅용). 생성 시 필수. |
subdomain | string (3~32) | 서비스 서브도메인. 패턴 ^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$(소문자·숫자·하이픈, 처음과 끝은 하이픈 불가). 생성 시 필수. |
upload | Refer<Upload> | 올릴 파일을 가리키는 참조. ZIP 또는 tar.gz이며, 루트에 index.html이 있고 자산은 상대 경로로 참조해야 합니다. |
url | string | 처리 완료 후 접속 URL. 시스템이 채웁니다. |
pageMetas | PageMeta[] | 문서별로 덮어쓸 메타 태그 값. 선택. 아래 문서별 메타데이터에서 설명합니다. |
customDomain | string | 연결한 커스텀 도메인. 선택. 아래 커스텀 도메인에서 설명합니다. |
서브도메인 확인
Web Hosting을 만들기 전에 쓰려는 서브도메인이 비어 있는지 확인할 수 있습니다. GET /web-hostings/availability?subdomain=...에 확인할 서브도메인을 subdomain 쿼리로 넘기면 됩니다.
응답은 다음 모양이며, available이 true면 그 서브도메인을 쓸 수 있습니다.
{ "subdomain": "dailywear-shop", "available": true }커스텀 도메인
기본 주소인 {subdomain}.weegloo.app 대신 직접 보유한 도메인을 Web Hosting에 연결할 수 있습니다. 연결한 도메인의 상태는 customDomain 객체로 표현되며, { id, domain, dns, cert } 모양입니다. dns와 cert는 각각 도메인 소유권 검증(DNS)과 인증서 발급(cert) 상태이며, 둘 다 { status, txtName, txtContent } 모양입니다. txtName·txtContent는 도메인 쪽에 등록해야 하는 DNS TXT 레코드의 이름과 값입니다.
{
"id": 1024,
"domain": "shop.dailywear.example",
"dns": {
"status": "pending",
"txtName": "_weegloo.shop.dailywear.example",
"txtContent": "weegloo-verify=3trmXRM3RqbgSnifyg7PWebVerifyEx"
},
"cert": {
"status": "pending",
"txtName": "_acme-challenge.shop.dailywear.example",
"txtContent": "acme-verify=3trmXRM3RqbgSnifyg7PWebCertEx"
}
}도메인 쪽에 TXT 레코드를 등록한 뒤 PUT /web-hostings/{webHostingId}/custom-domain/status/verify로 검증을 트리거하고, 현재 상태는 GET /web-hostings/{webHostingId}/custom-domain/status로 조회합니다. 검증이 끝나면 dns.status는 active, cert.status는 ok가 됩니다. 커스텀 도메인을 연결하지 않은 Web Hosting에 상태 조회를 호출하면 오류로 응답합니다(오류 참조).
문서별 메타데이터
올린 사이트의 문서마다 <head>의 메타 태그를 덮어쓸 수 있습니다. 검색 결과나 메신저 링크 미리보기에 나오는 제목·설명·이미지가 이 값으로 바뀝니다. 파일을 다시 빌드해 올리지 않고 요청 하나로 바꾸는 것이 목적입니다.
편집은 MarketApp 설치로 만들어진 Web Hosting에서만 됩니다. 파일을 upload로 교체하면 그때부터 편집할 수 없게 되고, sys.originMetas도 함께 비워집니다. 조건을 어긴 요청은 거부됩니다(오류 참조).
값은 pageMetas 배열에 담고, 항목 하나가 문서 하나를 가리킵니다.
| 속성 | 타입 | 설명 |
|---|---|---|
file | string (1~1024) | 대상 문서의 상대 경로. 예: index.html, about/index.html. |
meta | WebHostingMeta | 그 문서에 적용할 슬롯 값. |
sys.originMetas는 같은 모양이며, 덮어쓰기 전 문서가 원래 갖고 있던 값입니다. 되돌릴 때 이 값을 다시 보내면 됩니다.
슬롯
meta의 키를 슬롯이라 부릅니다. 슬롯 하나가 여러 태그를 함께 바꿉니다.
| 슬롯 | 최대 길이 | 바뀌는 태그 |
|---|---|---|
title | 200 | <title>, og:title, twitter:title |
description | 500 | description, og:description, twitter:description |
canonical | 2048 | link[rel=canonical], og:url |
image | 2048 | og:image, twitter:image |
siteName | 200 | og:site_name |
favicon | 2048 | link[rel=icon], link[rel="shortcut icon"], link[rel=apple-touch-icon] |
themeColor | 32 | theme-color |
태그가 문서에 없으면 새로 만들어 넣습니다. 다만 twitter:title·twitter:description·twitter:image와 link[rel="shortcut icon"]·link[rel=apple-touch-icon] 다섯은 예외로, 문서에 이미 있을 때만 값이 바뀌고 없으면 새로 만들어지지 않습니다.
값에 따른 결과
보낸 값이 어떤 모양인지에 따라 결과가 갈립니다.
| 요청에 담은 것 | 결과 |
|---|---|
| 슬롯 키를 넣지 않음 | 지금 설정이 그대로 남습니다. |
슬롯 키에 null | 지금 설정이 그대로 남습니다. |
| 슬롯 키에 빈 문자열 | 그 태그를 문서에서 지웁니다. |
| 슬롯 키에 값 | 그 값으로 덮어씁니다. |
pageMetas에서 문서 항목을 뺌 | 그 문서의 설정이 그대로 남습니다. |
pageMetas를 넣지 않음 | 모든 문서의 설정이 그대로 남습니다. |
아래 두 줄을 특히 주의하세요. 서버는 보낸 값을 문서와 슬롯 단위로 합칩니다. 그래서 배열에서 항목을 빼는 것으로는 설정이 지워지지 않고, 지우려면 그 슬롯에 빈 문자열을 명시해야 합니다.
빈 문자열은 태그를 지우는 것이지 원래대로 되돌리는 것이 아닙니다. 문서가 원래 갖고 있던 태그도 함께 사라집니다. 원래 값으로 되돌리려면 sys.originMetas에 남아 있는 값을 다시 보내세요.
다음은 index.html의 제목만 바꾸고 설명 태그는 지우는 요청 본문입니다.
{
"pageMetas": [
{
"file": "index.html",
"meta": {
"title": "데일리웨어 - 매일 입는 옷",
"description": ""
}
}
]
}pageMetas를 바꾸면 그 값을 실제 문서에 적용하는 처리가 다시 돌아갑니다. sys.state가 PENDING으로 돌아갔다가 COMPLETED로 오며, 그 사이에는 수정과 삭제가 거부됩니다.
오류
Web Hosting을 다룰 때 만나는 코드입니다. 모든 리소스에 공통인 코드는 공통 오류를 참조하세요.
| 코드 | 조건 |
|---|---|
WGL422031 | 배포 파일을 처리하는 중인 Web Hosting을 수정하거나 삭제하려 했습니다. 처리가 끝난 뒤에 다시 시도합니다. |
WGL422113 | 문서별 메타데이터를 편집할 수 없는 Web Hosting에 pageMetas를 보냈습니다. MarketApp 설치로 만들어지지 않았거나, 파일을 업로드로 교체한 뒤입니다. |
WGL500039 | 연결한 커스텀 도메인의 정보를 전송망에서 읽어 오지 못했습니다. |
WGL429001 | 커스텀 도메인이 없던 Web Hosting에 새로 붙이려 할 때, Organization의 커스텀 도메인 개수가 이미 요금제 한도에 이르렀습니다. 이미 있는 도메인을 바꾸는 것은 개수가 늘지 않으므로 이 검사를 받지 않습니다. |
API
아래 모든 엔드포인트의 기준 URL은 https://cma.weegloo.com/v1이며, Authorization 헤더에 CMA를 인증하는 Bearer 토큰이 필요합니다. 수정·부분 수정은 낙관적 동시성 제어를 위해 X-Weegloo-Version 헤더(현재 리소스의 sys.version)를 함께 보내야 합니다. 생성·삭제 요청에는 이 헤더가 없습니다.
관련 문서
- Upload API: 정적 파일 ZIP를 올려 Web Hosting 생성에 쓸 Upload를 받는 요청.
- Space: Web Hosting이 속한 Space.
