runlot
참조API

스키마

요청 본문과 응답의 모양입니다. 이름은 각 오퍼레이션의 본문 칸과 같습니다.

Slug

호스트네임의 한 라벨이 되므로 DNS 규칙을 따른다. 프로젝트 이름이 <name>.lvh.me 로 그대로 들어가기 때문에, 여기서 막지 않으면 만들 수 있지만 접속할 수 없는 프로젝트가 생긴다.

string

Error

필드필수설명
errorobject

Session

필드필수설명
tokenstring
expiresAtstring아니오
userUser

User

필드필수설명
userIdstring
providerstring
subjectstring
emailobject아니오
nameobject아니오

Org

필드필수설명
orgIdstring
slugSlug
namestring
personalboolean

OrgMembership

Org & object

Notification

필드필수설명
idinteger
kindstring사건의 종류 (docs/limits.md §3.1). 기계가 분기할 값이고, 사람이 읽을 문장은 대시보드와 메일 템플릿이 각각 만든다.
projectNamestring아니오프로젝트 사건이면 그 이름. org 사건(project_limit)에는 없다
keystring중복 제거 키 (kind 안에서). 같은 (kind, key) 는 24 시간에 하나다
detailobjectkind 마다 다른 숫자 몇 개. project_limit{limit, count}, 사용량 알림은 {bytes, capBytes}, 오퍼레이션 알림은 {opId, opKind, reason?} 다.
createdAtstring
sentAtstring아니오메일이 나간 시각. 없으면 아직 큐에 있거나 받을 이메일이 없었다

Project

필드필수설명
projectIdstring
orgSlugSlug
nameSlug
hostnamesstring[]
createdAtstring

ProjectDetail

Project & object

Placement

필드필수설명
statestring
epochinteger
homeNodeobject아니오
suspendedboolean수명주기 state 와 직교한다. 정지된 프로젝트도 state 는 active 일 수 있고, 해제하면 그 상태로 돌아간다.

Deployment

필드필수설명
deploymentIdstring
versioninteger
artifactShastring번들 tarball 의 sha256 (hex)
createdAtstring
createdByobject아니오
liveboolean

DatabaseEndpoint

필드필수설명
hoststring
portinteger
databasestring
sslmodestring

DatabaseTokenMeta

필드필수설명
userstring
expiresAtstring
createdAtstring

DatabaseToken

필드필수설명
userstring
passwordstring이 응답에만 실린다.
expiresAtstring
connectConnectInfoDatabaseConnect.connect 와 같은 모양이고 user/password 가 이 토큰의 것이다.

ConnectInfo

필드필수설명
hoststring프로젝트의 호스트네임이다. UUID 가 아닌 이유: front 는 SNI 로 배치를 정한다 (docs/actor-placement-routing.md §8).
portintegernode-front 의 wire 리스너 포트. CP 가 계산하는 값이 아니라 운영자가 front 와 CP 양쪽에 말해 주는 값이다 — 기본값은 internal/slotsDefaultFrontWirePort 한 자리에 있다.
databasestring프로젝트 UUID 다. front 가 startup 의 database 를 pin 의 UUID 로 덮어쓰므로 이것이 정본이다.
userstring부트스트랩 롤. 데이터베이스마다 따로라 이름이 겹칠 자리가 없다
passwordstring
sslmodestring끄는 값은 답하지 않는다. front 는 SSLRequest 를 거절 단계에서 끊으므로 disable 로는 애초에 붙지 않는다.

DatabaseConnect

필드필수설명
dbboolean
keyVersioninteger아니오이 프로젝트 DEK 의 버전이다 (docs/phase5.md C2). pg create 응답에만 실리고, 확보하지 못했으면 아예 없다 — 0 으로 답하지 않는 이유는 keyVersion=0 에 "평문 세대"라는 뜻이 이미 있어서, 확보 실패를 그 값으로 적으면 사용자가 평문 백업을 확정 사실로 읽기 때문이다. 없으면 백업 스케줄러가 나중에 확보한다.
connectConnectInfo

DatabaseExport

필드필수설명
projectIdstring
epochinteger이미지를 뜬 incarnation 이다. 같은 프로젝트라도 epoch 이 다르면 다른 데이터베이스이므로, 키만큼 중요한 값이다.
nodestring이미지를 뜬 노드
exportobject

DatabaseGenerations

필드필수설명
projectIdstring
epochinteger지금 도는 incarnation. 목록의 행은 옛 epoch 의 것도 있다
statestring배치 상태 (active·cold·restoring…)
lastCheckedAtstring아니오무변경 스킵의 마지막 하트비트. 비어 있으면 아직 한 번도 확인하지 않았다. 세대가 늘지 않는 것과 백업이 죽은 것을 가르는 값이라 목록에서 지울 수 없다 (docs/actor-placement-routing.md §4.6-1).
generationsGenerationRow[]최신 순. 빈 배열은 배열이지 null 이 아니다

GenerationRow

세대 하나. 필드 이름은 internal/backupprotoGenerationRow같다 — 액터가 내는 meta, 노드가 CP 에 보고하는 세대, 여기 실리는 행이 같은 이름을 쓰지 않으면 한 곳만 고쳐진 날 나머지가 조용히 0 으로 읽는다.

필드필수설명
epochinteger
seqintegerepoch 안에서 단조 증가한다. 복원은 (epoch, seq) 로 세대를 지목한다
keystring오프사이트 키 (gen/<project>/<epoch>/<stamp>-<seq>.feather)
bytesinteger오프사이트에 앉은 객체의 크기다. 봉인된 세대는 평문보다 크다 — admission 예약이 곱하는 것도 이 값이다.
sha256string
plainBytesinteger아니오봉투 안 평문(feather 이미지)의 크기. 평문 세대는 bytes 와 같다
keyVersioninteger아니오봉인에 쓴 DEK 버전. 0 은 평문이다 (DEK 없이 뜬 세대)
txnIdinteger아니오이미지가 담은 커밋 번호. 0 은 모름이다
kindstring아니오왜 생긴 세대인가. 판정에는 안 쓴다
createdAtstring
nodestring아니오세대를 뜬 노드
latestbooleangen/<project>/latest.json 이 가리키는 세대. 조건부 단조라 옛 epoch 의 늦은 세대는 이 표식을 못 가져간다 (docs/phase5.md A1).
finalboolean퇴거·삭제·복원 직전에 뜬 안전 사본. 정기 세대와 같은 표에 살지만 프루닝이 세지 않는다.

RestoreRequest

필드필수설명
epochinteger
seqinteger

DeleteRequest

필드필수설명
confirmstring프로젝트 이름과 정확히 같아야 한다. CLI 의 프롬프트만으로는 부족하다 — --yes 를 단 스크립트가 잘못된 디렉토리에서 돌면 프롬프트가 아예 뜨지 않는다.

OperationStarted

다단계 연산을 큐에 넣었다는 답이다 (202). 끝났다는 뜻이 아니다 — 진행은 …/database/operations/{opId} 로 본다.

필드필수설명
projectIdstring
opIdstring
kindstring
epochinteger
nodestring아니오

Operation

필드필수설명
opIdstring
kindstring
projectIdstring
phasestring지금 밟고 있는 단계 (draining·sealing·committing…). CLI 는 이 값이 바뀔 때만 줄을 찍는다 — 매 폴링마다 찍으면 로그가 진행이 아니라 폴링 주기를 보여 준다.
attemptinteger아니오
deferralsinteger아니오
ownerstring아니오
terminalCodestring아니오끝난 이유. aborted 는 사람이 중단한 것이고, 그 밖의 값은 실패다. 비어 있으면서 done 이면 성공이다.
failedAtstring아니오
errorstring아니오
doneboolean더 진행하지 않는다. 성공·실패·중단을 가르는 것은 terminalCode
retryAfterSecondsinteger아니오다음 시도까지 남은 초. 0 은 "지금 잡힐 차례"다 — 백오프가 붙은 뒤로 "진행 중"이 두 가지를 뜻하게 됐고, 이 값이 그 둘을 가른다.

Manifest

번들 안의 runlot.json. HTTP 본문으로 오가지 않지만 계약의 일부라 여기 둔다 — CLI 가 쓰고 cp-public 이 읽고 설정 생성기가 소비한다.

필드필수설명
mainobject아니오워커 진입점의 번들 내 경로. 없으면 순수 정적 사이트다 (Workers Static Assets 모델과 같다).
assetsobject아니오정적 자산 디렉토리의 번들 내 경로
compatibilityDatestring아니오
compatibilityFlagsstring[]아니오워커에 켤 workerd 호환 플래그. 허용 목록(internal/bundle. AllowedCompatibilityFlags)에 있는 것만 받고, 나머지는 배포가 거절된다 — unsafe_module 하나면 사용자 코드가 프로세스를 쥔다. experimental 은 생성기가 스스로 붙이므로 적지 않는다. nodejs_compat: node 내장 모듈(node:events, node:util, …)을 요구하는 라이브러리(TypeORM·Sequelize·Knex)를 위해서다. CLI 는 번들이 node 내장을 import 하면 이것을 적는다.
modulesManifestModule[]아니오진입점 옆에 따로 싣는 workerd 모듈. 지금은 wasm 뿐이다 — workerd 가 번들 안 WASM 컴파일을 막으므로 (Prisma 7 의 쿼리 컴파일러 같은) WASM 은 이 길로만 들어간다. name 은 워커 코드가 import 하는 지정자 그대로이고, path 는 번들 안의 파일이다. CLI 가 번들이 남긴 .wasm import 마다 하나씩 적는다.
frameworkstring아니오배포 도구가 프레임워크 어댑터로 묶었다는 표시 (docs/nextjs.md §3). next 면 노드가 OpenNext 가 찾는 바인딩 둘(ASSETS 별칭, WORKER_SELF_REFERENCE)을 더 렌더한다. 모르는 값은 배포가 거절된다.

ManifestModule

필드필수설명
namestring워커가 import 하는 지정자. 영숫자·._-, 슬래시 구분, . 으로 시작하지 않는다. worker 는 진입 모듈이라 쓸 수 없다.
typestring
pathstring번들 안의 파일 경로

Role

포함 관계다 — viewer 가 할 수 있는 일은 member 도, member 가 할 수 있는 일은 admin 도 할 수 있다 (cp/internal/public/public.go roleRank).

string

Member

필드필수설명
userIdstring
providerstring
subjectstring
emailobject아니오
nameobject아니오
roleRole
addedAtstring

SecretName

워커의 env.<NAME> 이 된다. DB·ASSETS(바인딩 env.db·env.assets 의 대문자 짝) 와 RUNLOT_ 접두는 예약이다 — 앞 둘은 이미 바인딩이고, 뒤는 노드가 프로세스 환경에 쓰는 이름 공간이다 (docs/phase6.md B4).

string

SecretMeta

필드필수설명
nameSecretName
versionintegerPUT 마다 1 씩 오른다. 노드는 이름·버전의 다이제스트로 교체를 판정한다
updatedAtstring

SecretList

필드필수설명
secretsSecretMeta[]

LogEvent

로그 스트림의 한 줄. type 으로 갈린다 — line 은 출력 한 줄, ping 은 15 초 하트비트, end 는 서버가 끝낸 이유.

필드필수설명
typestring
tsstring아니오노드가 줄을 받은 시각 (line)
epochinteger아니오
generationinteger아니오노드 안의 프로세스 세대. 교체되면 오른다
streamstring아니오runlot 은 워커가 아니라 노드가 쓴 줄이다 — 기동·종료 코드· 드롭된 줄 수 같은 사건.
linestring아니오줄 끝 개행 없이. 64 KiB 를 넘으면 잘리고 truncated 가 선다
truncatedboolean아니오
reasonstring아니오end 의 이유: process_exited·client_gone·node_shutdown

Usage

필드필수설명
projectIdstring
hoursinteger
rowsUsageRow[]
totalsobject
dbBytesinteger가장 최근 관측된 저장소 바이트. 관측이 없으면 0
objBytesinteger가장 최근 관측된 오브젝트 바이트. 게이지라 합이 아니다 — 시간대마다 더하면 같은 저장소를 시간 수만큼 센 값이 나온다 (docs/storage.md §4.5).

UsageRow

필드필수설명
hourstring시간대의 시작 (UTC
requestsinteger
cpuMsinteger
dbBytesinteger
objBytesinteger게이지 (마지막 관측값)
objOpsinteger누적 (델타의 합)

StorageStatus

프로젝트의 오브젝트 스토리지 한 조각 (docs/storage.md §7).

오브젝트는 DB 세대에 들어가지 않는다runlot pg restore 는 파일을 되돌리지 않는다 (§4.6). 그리고 read-after-write 는 보장되지만 list 는 지연될 수 있다.

필드필수설명
grantedboolean스토리지를 받았는가. 부여의 유일한 표현이 행의 존재라 (마이그레이션 0022), "부여됐지만 꺼져 있다" 는 상태는 없다.
prefixstring실제 객체 키의 접두. 사용자 키는 이 아래로만 붙고, 접두를 붙이는 것은 node-agent 다 — 사용자 키에 프로젝트 id 를 요구하면 그것을 바꿔 보내는 것이 곧 남의 버킷이다 (§4.4). 부여가 없으면 빈 문자열.
quotaBytesinteger상한 (무료 1 GiB). 초과하면 putpresign(PUT) 만 거절하고 get·list·delete 는 허용한다 — 쓰기와 함께 삭제를 막으면 한도에 갇힌 프로젝트에 탈출구가 없다 (§4.5). 부여가 없으면 0.
usedBytesinteger마지막으로 관측된 바이트. 노드의 보고 주기만큼 늦으므로 그 사이에 쿼터를 조금 넘길 수 있다 (§10 의 열린 항목). 관측이 없으면 0.

AccessPolicy

배포 접근 정책 (docs/access.md §3.1). 값이 없고 사실만 있다 — 비밀번호도 우회 시크릿도 해시로만 살고, 조회 API 는 그것을 돌려주지 않는다 (docs/access.md §6, 시크릿 표면의 규칙).

정책을 한 번도 안 정한 프로젝트는 mode: publicupdatedAt 이 없다. 그 둘을 가르는 이유는 화면이 "이 배포는 공개다" 를 상태 문장으로 말하기 때문이다 (§7).

필드필수설명
modestringpublic 은 아무나, org 는 프로젝트가 속한 org 의 member 이상, password 는 프로젝트당 하나의 공유 비밀번호다. 넷째 값이 없는 것은 그것이 곧 인가(A3)의 질문이기 때문이다 — "이메일 도메인이 @acme.com 인 사람" 은 경계의 질문이 아니다.
hasPasswordboolean비밀번호가 저장돼 있는가. 값은 안 나간다
hasBypassboolean자동화 우회 시크릿이 있는가. 값은 만들 때 한 번만 보인다
updatedAtstring아니오한 번도 안 정했으면 생략된다

AccessBypass

자동화 우회 시크릿. 이 응답에만 있다 — 다시 볼 수 없고, 재발급은 옛 값을 즉시 죽인다 (docs/access.md §3.6).

필드필수설명
secretstringRunlot-Access-Bypass 헤더에 그대로 싣는다

AccessAuthorize

보호된 배포로 돌아가는 주소. 1 회용 코드(60 초·단일 사용·그 프로젝트 전용)가 쿼리에 실려 있고, front 가 그것을 교환해 쿠키를 심은 뒤 쿼리 없는 원 URL 로 다시 302 한다 — 그 302 가 코드를 주소창에서 지운다 (docs/access.md §3.4).

필드필수설명
redirectstring

AuthProvider

프로젝트가 자기 앱을 등록하는 소셜 프로바이더. 셋인 이유는 이 시장의 기본값이 셋이기 때문이고, 넷째는 수요가 오면 붙는다 (docs/auth.md §12 — SAML·OIDC 는 기업 고객이 올 때).

string

AuthSettings

인증의 손잡이 전부 (docs/auth.md §9). 넷뿐인 것이 요점이다 — 이메일 템플릿 편집기·MFA·기기 목록은 §12 가 명시적으로 미룬 것들이다.

필드필수설명
allowSignupboolean새 가입을 받는가. 끄면 이미 있는 사람만 로그인한다 — 초대제 앱이나 베타를 닫을 때 쓴다.
requireVerifiedEmailboolean이메일을 확인해야 로그인이 되는가. 켜면 확인 전 사용자는 env.auth.user(request) 에서 세션을 못 얻는다.
sessionDaysinteger세션 쿠키의 수명 (일). 세션 표의 크기를 정하는 손잡이이기도 하다 — 프로젝트 DB 는 150 MB 상한 안이고 (docs/auth.md §13) 활성 사용자 만 명 × 기기 셋이면 세션이 6 MB 다.
brandAuthBrand

AuthBrand

호스팅 로그인 페이지의 브랜딩 (docs/auth.md §4). 셋뿐이다 — 그 이상을 원하면 자기 페이지를 만들고 §5 의 JSON 끝점을 부른다. 셋 다 빈 문자열이면 프로젝트 이름과 기본 토큰으로 그린다.

필드필수설명
namestring페이지 위의 이름. 비면 프로젝트 이름
logostring로고 이미지 주소. 비면 안 그린다
colorstring강조색 #rrggbb. 비면 @runlot/design 의 기본

AuthProviderMeta

등록된 프로바이더 하나. 시크릿이 없다 — client id 는 브라우저에도 나가는 공개값이고, client secret 은 봉인돼 어느 응답에도 안 나온다 (시크릿 표면의 규칙, docs/access.md §6).

필드필수설명
providerAuthProvider
clientIdstring프로바이더가 준 공개 id
updatedAtstring마지막으로 등록·교체한 시각

AuthStatus

프로젝트의 최종 사용자 인증 한 조각 (docs/auth.md §9).

가입자는 여기 없다. 사람은 프로젝트 Postgres 의 runlot_auth 스키마에 살고 (§6) 그 표는 프로젝트 삭제·pg export·세대 백업·복원을 따라 움직인다. CP 가 그 표를 비추면 수명이 둘로 갈린다.

필드필수설명
grantedboolean인증을 켰는가. 부여의 유일한 표현이 행의 존재라 "켜졌지만 꺼져 있다" 는 상태는 없다. 꺼져 있으면 settings 는 기본값이고 providers 는 빈 배열이다.
settingsAuthSettings
providersAuthProviderMeta[]등록된 프로바이더. 등록 순서가 아니라 이름 순이다
hostsstring[]이 프로젝트가 답하는 호스트네임 전부. 프로바이더 콘솔에 등록할 콜백 URL 이 호스트마다 하나씩 나온다 — https://<host>/__runlot/auth/callback/<provider>. 호스트를 붙일 때마다 프로바이더에 콜백을 더해야 한다. 화면과 CLI 가 목록을 그대로 찍는 이유가 그것이다 — 빠뜨린 호스트는 그 호스트에서만 로그인이 깨지고, 그 실패는 콘솔에서만 보인다.

AuthSettingsPatch

설정의 부분 갱신. 준 칸만 바뀐다 — 스위치 하나를 누를 때마다 전체를 실어 보내면 두 사람이 같은 카드를 만질 때 나중 저장이 앞 저장을 덮는다.

필드필수설명
settingsobjectAuthSettings 의 부분집합. 빈 객체는 아무것도 안 바꾼다

AuthProviderPut

프로바이더 자격 증명. 둘 다 필수인 이유는 교체가 같은 PUT 이기 때문이다 — id 만 보내고 시크릿을 생략하면 "옛 시크릿이 남았는가" 가 응답으로 확인되지 않는 사실이 된다.

필드필수설명
clientIdstring프로바이더가 준 공개 id
clientSecretstring봉인해 저장한다. 어느 응답에도 다시 나오지 않는다 — 잃으면 프로바이더 콘솔에서 새로 발급해 다시 PUT 한다.

Hostname

프로젝트에 붙은 이름 하나. statepending_dns(소유 확인 중) → pending_tls(인증서 발급 중) → active(연결됨) 로 가고, 실패는 error 다. active 인 행만 라우팅에 실린다.

필드필수설명
hostnamestringpunycode·소문자로 정규화된 이름
kindstringdefault<project>--<org>.<app-domain>, custom 은 고객 도메인
statestring
lastErrorstring아니오마지막 확인이 실패한 이유. 사용자가 자기 DNS 를 고칠 때 읽는다
createdAtstring
verifyHostnameVerify아니오

HostnameVerify

고객이 자기 DNS 에 넣어야 하는 두 줄. 둘 중 하나만 맞으면 소유가 증명된다 — CNAME 은 연결까지 겸하므로 그쪽이 기본 안내다. 값은 CP 가 계산해서 내려 준다 (fallback origin 이 배치 설정이라, 클라이언트가 각자 적어 두면 그 값이 바뀌는 날 갈라진다).

필드필수설명
cnameHostnameRecord
txtHostnameRecord

HostnameRecord

필드필수설명
namestring레코드 이름
targetstring아니오CNAME 대상
valuestring아니오TXT 값

HostnameList

필드필수설명
hostnamesHostname[]

Zone

우리 권한 DNS 의 존 하나 (docs/domains.md §4.3). serial 이 곧 rev 다 — 변경마다 오르고, publishedSerial 이 따라잡으면 네임서버가 그 내용을 답하고 있다는 뜻이다.

필드필수설명
zoneIdstring
orgIdstring
namestringexample.com (소문자 punycode, 끝점 없음)
serialinteger
publishedSerialinteger마지막으로 존 파일에 쓴 serial. serial 보다 작으면 아직 반영 중이다 (보통 2 초)
dnssecstring
dsstring[]부모에 올릴 DS. 등록기관이 우리면 D3 가 올리고, 아니면 화면이 보여 준다
delegationstring주기 검사 결과. 등록기관의 NS 가 우리를 가리키는가
delegationCheckedAtstring아니오
nameserversstring[]등록기관에 넣어야 하는 NS. 존의 값이 아니라 CP 설정의 사본이다
createdAtstring

ZoneDetail

존 하나와 그 레코드 전부.

Zone & object

RRset

(이름, 타입) 하나의 값 묶음. managedBy 가 있으면 다른 층이 만든 행이고 편집기에서 잠긴다 — system(존의 NS), hostname:<host>(앱 연결), acme(인증서).

필드필수설명
namestring상대 이름. @ 는 apex
typestring
ttlinteger
recordsstring[]
managedBystring아니오
updatedAtstring

ZoneList

필드필수설명
zonesZone[]

DomainAvailability

이름 하나의 가용성과 값. 도매가는 없다 — 원가는 우리 운영의 사실이지 고객의 사실이 아니다 (cp-core 는 운영자를 위해 함께 준다).

필드필수설명
namestring
availableboolean
premiumboolean레지스트리가 따로 값을 매긴 이름. 등록·갱신 값이 크게 다르다
priceCentsinteger첫 등록 1 년 (원화 아님 — 센트)
renewalCentsinteger갱신 1 년

DomainContact

등록자 연락처. 고객의 것이다 — ICANN 검증 메일이 이 주소로 가고, 15 일 안에 확인하지 않으면 도메인이 정지된다. 화면은 등록 전에 그 사실을 말해야 한다 (docs/domains.md §5.5).

필드필수설명
firstNamestring
lastNamestring
orgstring아니오
emailstring
phonestring
address1string
address2string아니오
citystring
statestring아니오
zipstring
countrystringISO 3166-1 alpha-2

Domain

도메인 하나. 만료일·잠금·네임서버는 등록기관 정본의 사본이고 domain-sync(6 h)가 맞춘다 (docs/domains.md §5.4).

필드필수설명
namestring
zoneIdstring아니오우리 존. 구매·가져오기 때 항상 만들어진다
registrarstringexternal 은 남의 계정에 있는 도메인이다 — 갱신·잠금은 우리 일이 아니다
statestring만료일에서 파생된다: 만료 30 일 전부터 expiring, 만료 뒤 유예 30 일이 expired, 그 뒤 30 일이 redemption(복구 수수료), 그다음이 released. transferred_out 은 등록기관이 "우리 계정에 없다" 고 답했을 때다.
expiresAtstring아니오
autoRenewboolean고객 의사다. 등록기관 쪽 자동 갱신은 언제나 켜져 있다 — 우리가 먼저 갱신하고 뒤에 청구한다 (§5.4).
lockedboolean이전 잠금
nameserversstring[]
yearsinteger
priceCentsinteger아니오고객이 낸 값
sagaStepstringdone 이 아니면 구매가 아직 진행 중이다 (docs/domains.md §5.3)
sagaErrorstring아니오멈춘 이유. 상태가 failed 가 아니어도 실릴 수 있다
createdAtstring

DomainEvent

원장 한 줄 (append-only). kindpurchase·register_attempt· register·register_reconciled·zone·ds·done·renew·lock· unlock·auto_renew·auth_code·state·transfer_out·import· error 등이다. 이전 코드와 시크릿은 여기 담기지 않는다.

필드필수설명
eventIdinteger
kindstring
detailobject아니오
atstring

DomainDetail

Domain & object

DomainList

필드필수설명
domainsDomain[]

이 페이지에서