Web Hosting

Web Hosting은 빌드한 정적 웹사이트를 Space에 올려 {subdomain}.weegloo.app 주소로 서비스하는 리소스입니다. 옷가게 쇼핑몰을 예로 들면, 빌드한 쇼핑몰 사이트를 dailywear-shop.weegloo.app으로 띄우는 것이 Web Hosting 한 건입니다.

올리는 순서는 다음과 같습니다. 먼저 빌드 결과를 ZIP 또는 tar.gz로 묶어 Upload API로 올려 Upload 하나를 받습니다. 그 Upload를 참조해 POST /web-hostingsWeb Hosting을 만듭니다. 시스템이 올린 파일을 처리해 sys.stateCOMPLETED가 되면 url로 사이트에 접속할 수 있습니다. CMA에서 Web HostingSpace 하위 리소스이며, 경로는 /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·updatedByRefer 모양({ "sys": { "id", "type": "Refer", "targetType" } })으로 들어갑니다.

속성타입설명
idstring리소스 고유 식별자. 단일 조회·수정·삭제 경로의 {webHostingId}에 들어갑니다.
typestring리소스 종류. Web Hosting은 항상 "WebHosting".
spaceRefer<Space>Web Hosting이 속한 Space.
createdByRefer<User>생성한 사용자.
createdAtstring (date-time)생성 시각.
updatedByRefer<User>마지막으로 수정한 사용자.
updatedAtstring (date-time)마지막 수정 시각.
statestring (enum)배포 처리 상태. 아래 4가지 중 하나.
errorstring처리 실패 시 그 사유. 실패가 아니면 비어 있습니다.
totalFileSizeinteger올린 파일의 총 크기(바이트).
originMetasPageMeta[]문서가 원래 갖고 있던 메타 태그 값. MarketApp 설치로 만들어진 Web Hosting에만 채워집니다. 아래 문서별 메타데이터에서 설명합니다.
versioninteger (≥1)리소스 버전. 생성·수정마다 1씩 올라갑니다. 수정·부분 수정 요청에 x-weegloo-version으로 실어야 하는 값입니다.

state는 올린 파일을 배포하는 처리 단계를 나타냅니다. Content의 발행 상태가 아니며, Web Hosting에는 발행이나 보관 개념이 없습니다. 파일을 처리해 COMPLETED가 되면 url로 사이트에 접속됩니다.

state의미
PENDING처리 대기 중.
PROCESSING처리 중.
COMPLETED처리 완료. url로 접속 가능합니다.
FAILED처리 실패. 사유는 sys.error에 담깁니다.

본문 속성

Web Hosting의 본문 속성은 다음과 같습니다.

속성타입설명
namestring (1~64)Web Hosting 이름. 생성 시 필수.
descriptionstring (≤128)설명. 선택.
isSpaboolean단일 페이지 앱 여부. true면 모든 경로 요청을 index.html로 보냅니다(SPA 라우팅용). 생성 시 필수.
subdomainstring (3~32)서비스 서브도메인. 패턴 ^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$(소문자·숫자·하이픈, 처음과 끝은 하이픈 불가). 생성 시 필수.
uploadRefer<Upload>올릴 파일을 가리키는 참조. ZIP 또는 tar.gz이며, 루트에 index.html이 있고 자산은 상대 경로로 참조해야 합니다.
urlstring처리 완료 후 접속 URL. 시스템이 채웁니다.
pageMetasPageMeta[]문서별로 덮어쓸 메타 태그 값. 선택. 아래 문서별 메타데이터에서 설명합니다.
customDomainstring연결한 커스텀 도메인. 선택. 아래 커스텀 도메인에서 설명합니다.

서브도메인 확인

Web Hosting을 만들기 전에 쓰려는 서브도메인이 비어 있는지 확인할 수 있습니다. GET /web-hostings/availability?subdomain=...에 확인할 서브도메인을 subdomain 쿼리로 넘기면 됩니다.

응답은 다음 모양이며, availabletrue면 그 서브도메인을 쓸 수 있습니다.

{ "subdomain": "dailywear-shop", "available": true }

커스텀 도메인

기본 주소인 {subdomain}.weegloo.app 대신 직접 보유한 도메인을 Web Hosting에 연결할 수 있습니다. 연결한 도메인의 상태는 customDomain 객체로 표현되며, { id, domain, dns, cert } 모양입니다. dnscert는 각각 도메인 소유권 검증(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.statusactive, cert.statusok가 됩니다. 커스텀 도메인을 연결하지 않은 Web Hosting에 상태 조회를 호출하면 오류로 응답합니다(오류 참조).

문서별 메타데이터

올린 사이트의 문서마다 <head>의 메타 태그를 덮어쓸 수 있습니다. 검색 결과나 메신저 링크 미리보기에 나오는 제목·설명·이미지가 이 값으로 바뀝니다. 파일을 다시 빌드해 올리지 않고 요청 하나로 바꾸는 것이 목적입니다.

편집은 MarketApp 설치로 만들어진 Web Hosting에서만 됩니다. 파일을 upload로 교체하면 그때부터 편집할 수 없게 되고, sys.originMetas도 함께 비워집니다. 조건을 어긴 요청은 거부됩니다(오류 참조).

값은 pageMetas 배열에 담고, 항목 하나가 문서 하나를 가리킵니다.

속성타입설명
filestring (1~1024)대상 문서의 상대 경로. 예: index.html, about/index.html.
metaWebHostingMeta그 문서에 적용할 슬롯 값.

sys.originMetas는 같은 모양이며, 덮어쓰기 전 문서가 원래 갖고 있던 값입니다. 되돌릴 때 이 값을 다시 보내면 됩니다.

슬롯

meta의 키를 슬롯이라 부릅니다. 슬롯 하나가 여러 태그를 함께 바꿉니다.

슬롯최대 길이바뀌는 태그
title200<title>, og:title, twitter:title
description500description, og:description, twitter:description
canonical2048link[rel=canonical], og:url
image2048og:image, twitter:image
siteName200og:site_name
favicon2048link[rel=icon], link[rel="shortcut icon"], link[rel=apple-touch-icon]
themeColor32theme-color

태그가 문서에 없으면 새로 만들어 넣습니다. 다만 twitter:title·twitter:description·twitter:imagelink[rel="shortcut icon"]·link[rel=apple-touch-icon] 다섯은 예외로, 문서에 이미 있을 때만 값이 바뀌고 없으면 새로 만들어지지 않습니다.

값에 따른 결과

보낸 값이 어떤 모양인지에 따라 결과가 갈립니다.

요청에 담은 것결과
슬롯 키를 넣지 않음지금 설정이 그대로 남습니다.
슬롯 키에 null지금 설정이 그대로 남습니다.
슬롯 키에 빈 문자열그 태그를 문서에서 지웁니다.
슬롯 키에 값그 값으로 덮어씁니다.
pageMetas에서 문서 항목을 뺌그 문서의 설정이 그대로 남습니다.
pageMetas를 넣지 않음모든 문서의 설정이 그대로 남습니다.

아래 두 줄을 특히 주의하세요. 서버는 보낸 값을 문서와 슬롯 단위로 합칩니다. 그래서 배열에서 항목을 빼는 것으로는 설정이 지워지지 않고, 지우려면 그 슬롯에 빈 문자열을 명시해야 합니다.

빈 문자열은 태그를 지우는 것이지 원래대로 되돌리는 것이 아닙니다. 문서가 원래 갖고 있던 태그도 함께 사라집니다. 원래 값으로 되돌리려면 sys.originMetas에 남아 있는 값을 다시 보내세요.

다음은 index.html의 제목만 바꾸고 설명 태그는 지우는 요청 본문입니다.

{
  "pageMetas": [
    {
      "file": "index.html",
      "meta": {
        "title": "데일리웨어 - 매일 입는 옷",
        "description": ""
      }
    }
  ]
}

pageMetas를 바꾸면 그 값을 실제 문서에 적용하는 처리가 다시 돌아갑니다. sys.statePENDING으로 돌아갔다가 COMPLETED로 오며, 그 사이에는 수정과 삭제가 거부됩니다.

오류

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

코드조건
WGL422031배포 파일을 처리하는 중인 Web Hosting을 수정하거나 삭제하려 했습니다. 처리가 끝난 뒤에 다시 시도합니다.
WGL422113문서별 메타데이터를 편집할 수 없는 Web HostingpageMetas를 보냈습니다. 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.