데이터베이스
database 카테고리의 API 작업 14개를 다룹니다.
| 메서드 | 경로 | 설명 |
|---|---|---|
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/database | 데이터베이스 사용 가능 여부 |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/database | 이전 데이터베이스를 삭제한 뒤 새 데이터베이스를 만듭니다 |
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/database/connect | psql 또는 드라이버로 연결하는 데 필요한 정보 |
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/database/endpoint | 자격 증명 없는 연결 정보(runlot port-forward) |
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/database/tokens | 유효한 단기 자격 증명 목록 |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/database/tokens | 단기 자동화용 자격 증명을 발급합니다(runlot pg token) |
| DELETE | /v1/orgs/{orgSlug}/projects/{projectName}/database/tokens/{tokenUser} | 단기 자격 증명을 폐기합니다 |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/database/execute | 문 하나 실행 (대시보드의 SQL 콘솔) |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/database/export | 진단 이미지를 생성합니다(runlot pg export) |
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/database/generations | 백업 세대 목록(runlot pg generations) |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/database/restore | 특정 세대로 복원합니다(runlot pg restore) |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/database/delete | 데이터베이스를 삭제합니다(runlot pg delete) |
| GET | /v1/orgs/{orgSlug}/projects/{projectName}/database/operations/{opId} | 작업 하나의 진행 상황 |
| POST | /v1/orgs/{orgSlug}/projects/{projectName}/database/operations/{opId}/abort | 진행 중인 작업을 중단합니다(runlot pg abort) |
GET /v1/orgs/{orgSlug}/projects/{projectName}/database
응답은 단순히 {db: bool}입니다. 크기나 세대 정보는 여기에 포함되지 않습니다.
자격 증명은 반환되지 않습니다. viewer 이상이면 호출할 수 있으며, 연결 정보는 /database/connect에 있습니다.
operationId getDatabase
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 데이터베이스 사용 가능 여부 | object |
| 403 | — | — |
| 404 | — | — |
POST /v1/orgs/{orgSlug}/projects/{projectName}/database
모든 프로젝트는 처음부터 데이터베이스를 가집니다. 이 호출은 삭제 뒤 비어 있는 새 데이터베이스를 만들고, 꺼 둔 기록을 지워 이후 배포에서도 유지되게 합니다. 연결 정보를 반환합니다. 잠시 후 실행 중인 worker가 연결된 env.db를 인식합니다. 재배포는 필요하지 않습니다.
이 작업은 멱등적이며 비밀번호를 재발급하지 않습니다. 두 번째 호출도 동일한 연결 정보를 반환하므로, 첫 번째 응답에서 저장한 연결 문자열이 계속 동작합니다.
operationId createDatabase
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 자격 증명 및 연결 정보 | DatabaseConnect |
| 403 | — | — |
| 404 | — | — |
GET /v1/orgs/{orgSlug}/projects/{projectName}/database/connect
psql이나 다른 PostgreSQL 드라이버로 연결하는 데 필요한 호스트, 포트, 데이터베이스 이름, 사용자, 비밀번호, sslmode를 반환합니다. member 이상의 권한이 필요합니다. viewer는 데이터베이스가 존재한다는 사실은 확인할 수 있지만 비밀번호는 볼 수 없습니다.
operationId getDatabaseConnect
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 연결 정보 | DatabaseConnect |
| 403 | — | — |
| 404 | 프로젝트가 존재하지 않거나, 데이터베이스가 아직 생성되지 않았습니다 | Error |
GET /v1/orgs/{orgSlug}/projects/{projectName}/database/endpoint
호스트, 포트, 데이터베이스, sslmode만 반환하며 비밀 정보가 없으므로 viewer 이상이면 호출할 수 있습니다. runlot port-forward는 비밀번호가 아니라 로그인 세션으로 인증하므로 이 엔드포인트만으로 충분합니다.
operationId getDatabaseEndpoint
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 엔드포인트 | object |
| 403 | — | — |
| 404 | — | — |
GET /v1/orgs/{orgSlug}/projects/{projectName}/database/tokens
프로젝트의 단기 데이터베이스 자격 증명 목록을 반환합니다. 비밀번호는 포함되지 않습니다. member 이상의 권한이 필요합니다.
operationId listDatabaseTokens
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 목록 조회 | object |
| 403 | — | — |
| 404 | — | — |
POST /v1/orgs/{orgSlug}/projects/{projectName}/database/tokens
연결 문자열에 사용할 사용자/비밀번호 쌍을 발급합니다. 비밀번호는 이 응답에서만 표시되며 SCRAM 검증자만 저장되므로, 비밀번호를 분실하면 재발급해야 합니다. 세션은 여전히 프로젝트 자체의 데이터베이스 역할로 열리며, 토큰 사용자는 로그인 이름일 뿐입니다. member 이상의 권한이 필요합니다.
operationId createDatabaseToken
요청 본문: application/json · object
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 201 | 발급된 자격 증명 | DatabaseToken |
| 400 | — | — |
| 403 | — | — |
| 404 | — | — |
DELETE /v1/orgs/{orgSlug}/projects/{projectName}/database/tokens/{tokenUser}
이후의 연결은 거부됩니다. 존재하지 않는 자격 증명을 삭제하려 하면 404를 반환합니다. member 이상이 사용할 수 있습니다.
operationId deleteDatabaseToken
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 204 | 취소됨 | — |
| 403 | — | — |
| 404 | — | — |
POST /v1/orgs/{orgSlug}/projects/{projectName}/database/execute
프로젝트의 데이터베이스에서 SQL 문 하나를 실행하고 결과 행을 반환합니다. 이는 대시보드의 SQL 콘솔을 지원하는 API이며, 터미널에서는 대신 직접 연결하는 runlot pg execute를 사용하세요.
이 문은 …/database/connect가 member에게 psql용으로 제공하는 것과 동일한 호스트, 포트, sslmode, 자격 증명을 사용하여 일반 PostgreSQL 연결을 통해 실행되므로, 10초의 문 실행 제한을 포함해 일반 연결에 적용되는 모든 규칙이 여기에도 동일하게 적용됩니다.
readOnly의 기본값은 true이며, 필드가 없으면 true로 간주됩니다. 읽기 전용 모드는 BEGIN … READ ONLY 내에서 실행되며 항상 롤백되고, 절대 커밋되지 않습니다.
값은 항상 문자열 또는 null로 반환되며 JSON 숫자로는 반환되지 않으므로 큰 정수 id도 정확한 자릿수를 유지합니다. NULL은 null이고 빈 문자열은 ""입니다.
최대 500개의 행이 나열됩니다. 이 상한은 응답에만 적용되며 문(statement)에는 추가되지 않으므로, rowCount는 여전히 문이 실제로 수행한 작업을 보고하며 truncated는 목록이 잘렸음을 알려줍니다.
쓰기 모드는 대시보드 세션에 속합니다. 개인 액세스 토큰은 db:read로 이 경로에 접근해 읽기 전용 문장을 실행합니다. 토큰으로 readOnly: false를 요청하면 403 console_write_needs_session이 반환됩니다. 이를 여는 스코프는 없습니다. 쓰기가 필요한 자격 증명은 …/database/connect 또는 …/database/tokens를 거쳐 직접 연결하며, 그 자격 증명이 가진 권한은 토큰에 명시됩니다.
member 이상의 권한이 필요합니다. 쓰기 작업은 db.execute 감사 이벤트를 남기지만 읽기 작업은 남기지 않습니다.
operationId executeSQL
요청 본문: application/json · ExecuteRequest
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 문이 실행되었습니다 | ExecuteResult |
| 400 | 데이터베이스가 문을 거부했습니다. code는 sql_error이고 details.sqlstate에는 PostgreSQL 고유의 5자리 오류 코드가 담깁니다. details에는 detail, hint, position도 포함될 수 있습니다. | Error |
| 403 | insufficient_scope — 토큰에 db:read도, 그보다 넓은 스코프도 없습니다. 또는 console_write_needs_session — 대시보드 세션이 아닌 곳에서 readOnly: false를 요청했습니다. | Error |
| 404 | — | — |
| 502 | 이 프로젝트의 데이터베이스에 연결할 수 없음 (console_unreachable) | — |
| 504 | 데이터베이스가 왕복 제한 시간 내에 응답하지 않음 (console_timeout) | — |
POST /v1/orgs/{orgSlug}/projects/{projectName}/database/export
이는 백업이 아닙니다. 현재 시점의 데이터베이스에 대한 변경 불가능한 진단 이미지를 생성합니다. 백업 포인터를 이동시키지 않고 보존 기간에 영향을 주지 않으며 복원 시 선택할 수 없습니다.
예약된 백업은 별개이며 자체 시간별 일정에 따라 실행됩니다. …/database/generations에서 목록을 확인하고 …/database/restore에서 하나를 선택하세요. 진단 이미지는 이 기록에 전혀 포함되지 않습니다. 복원에서 선택할 수 없으며 정리(pruning) 대상에서도 제외됩니다.
이는 멱등적이지 않습니다. 호출할 때마다 이미지가 하나씩 더 생성됩니다.
이미지가 데이터베이스 전체를 포함하므로 member 이상의 권한이 필요합니다.
속도가 느립니다. 덤프가 완료된 후에야 응답이 도착하며, 소요 시간은 데이터베이스 크기에 비례합니다.
operationId exportDatabase
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 생성된 진단 키 | DatabaseExport |
| 403 | — | — |
| 404 | 프로젝트가 존재하지 않거나, 데이터베이스가 아직 생성되지 않았습니다 | Error |
| 409 | 프로젝트가 일시 중단되었습니다 (suspended). 진단 이미지는 실행 중인 프로젝트에서만 생성할 수 있습니다. 일시 중단된 프로젝트에서 데이터를 가져오려면 대신 복원을 사용하세요. | Error |
| 502 | 이미지를 생성하지 못했습니다 (export_failed) | Error |
| 503 | 현재 프로젝트를 내보낼 수 없습니다. 실행 중인 프로세스가 없거나(no_home_node) 서비스가 일시적으로 사용할 수 없는 상태입니다(no_node_admin). | Error |
GET /v1/orgs/{orgSlug}/projects/{projectName}/database/generations
복원 시 선택할 수 있는 백업 세대를 최신순으로 나열하며, 각 항목에는 저장소 키, 크기, sha256 다이제스트가 포함되어 복원이 수신한 내용을 검증할 수 있습니다.
lastCheckedAt은 백업이 마지막으로 확인된 시점을 기록합니다. 진행되지 않는 세대와 작동을 멈춘 백업은 서로 다른 문제이며, 이 값이 둘을 구분해 줍니다. 비어 있으면 아직 확인이 실행되지 않은 것입니다.
member 이상의 권한이 필요합니다.
데이터베이스가 활성화되어 있지 않아도 됩니다. runlot pg delete 이후에도 최종 안전 세대가 유지되므로 삭제 후에도 여기에 계속 표시됩니다.
objects는 동일한 기록의 Durable Object 절반이며, 프로젝트의 복원 가능한 상태는 두 부분의 합집합이므로 데이터베이스 세대와 함께 반환됩니다.
두 절반은 독립적으로 타이밍이 결정되므로 objects.atomic은 항상 false입니다. objects.restorable은 objects.available && objects.complete입니다. 이 값이 false이면 구성 요소가 누락되었거나 공백이 발견되어 복원이 즉시 거부됩니다. restorable=true는 카탈로그가 자격이 있다는 것만을 의미하며, 예를 들어 노드에 연결할 수 없거나 저장된 아카이브가 손실되거나 손상된 경우 복원이 이후에도 실패할 수 있습니다.
objects는 세대별이 아니라 전체 프로젝트에 대해 한 시점(기본값: 현재)에 선택됩니다. 복원은 자체 lastAt을 가진 특정 (epoch, seq) 세대 하나를 대상으로 합니다. 객체 절반이 해당 세대에 대해 자격이 있는지 확인하려면 ?at=<해당 세대의 lastAt>으로 이 엔드포인트를 다시 호출하세요. 두 답변은 서로 다를 수 있습니다.
operationId listGenerations
| 매개변수 | 위치 | 필수 | 타입 | 설명 |
|---|---|---|---|---|
at | query | 아니오 | 문자열 | 객체 절반만을 이 시점 또는 그 이전의 최신 구성 요소로 좁힙니다. 데이터베이스 세대는 항상 전체가 나열됩니다. |
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 세대 목록, 최신순 | DatabaseGenerations |
| 403 | — | — |
| 404 | — | — |
POST /v1/orgs/{orgSlug}/projects/{projectName}/database/restore
복원은 프로젝트의 데이터베이스를 중지하고 그 내용을 선택한 세대로 교체한 다음 다시 시작합니다. 복원 직전의 데이터는 먼저 아카이브되므로 되돌릴 방법이 있습니다.
선택한 세대 이후에 이루어진 모든 쓰기는 손실됩니다. 이 작업에는 admin 이상의 권한이 필요하며, CLI는 프로젝트 이름을 다시 입력하도록 요청합니다.
프로젝트에 Durable Object가 있는 경우 동일한 작업으로 이들도 복원됩니다. 영향을 받는 각 객체는 먼저 아카이브된 후 선택한 구성 요소로 되돌려집니다. 복원 대상 이후에 배치된 객체는 제거됩니다. 객체 구성 요소가 누락된 경우 프로젝트의 일부만 복원하는 대신 데이터베이스를 포함한 전체 복원이 거부됩니다.
전달하려는 세대에 대해, 이 작업을 호출하기 전에 objects.restorable을 확인하세요. 먼저 …/database/generations?at=<the chosen generation's lastAt>를 호출하세요: 객체 쪽은 여기서 보내는 (epoch, seq)와 무관하게 자신의 순간에 따로 선택되므로, 다른 순간에 읽은 restorable=true는 다른 질문에 대한 답입니다. 시점이 정확한 restorable=true라 해도 이는 자격이 있다는 것일 뿐 보장이 아닙니다 — 복원은 시작된 후에도 여전히 실패할 수 있습니다.
서버는 latest를 해석하지 않습니다. 목록에서 확인한 정확한 (epoch, seq)를 전달하세요. 그러면 그 사이에 생성된 세대가 다른 곳으로 보내지 않습니다.
결과 대신 202와 operation id를 반환합니다. 진행 상황은 …/database/operations/{opId}를 폴링하세요.
operationId restoreDatabase
요청 본문: application/json · RestoreRequest
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 202 | 작업을 시작했습니다 | OperationStarted |
| 400 | — | — |
| 403 | — | — |
| 404 | 프로젝트가 존재하지 않거나, 데이터베이스가 아직 생성되지 않았습니다 | Error |
| 409 | 다른 작업이 이미 진행 중이거나(operation_in_progress), 프로젝트가 정지된 상태입니다(suspended). | Error |
| 503 | 현재 프로젝트를 복원할 수 없습니다(예: 사용 가능한 용량이 없음) | Error |
POST /v1/orgs/{orgSlug}/projects/{projectName}/database/delete
프로젝트의 데이터베이스를 삭제합니다. 마지막 안전 세대가 유지되므로 이후에도 데이터를 나열하고 복원할 수 있습니다. 삭제가 완료되면 worker는 env.db 없이 실행됩니다. admin 이상 권한이 필요합니다.
이 작업은 최종 사용자 auth도 끕니다. 구독자 기록은 프로젝트의 데이터베이스 안에 있으므로 함께 삭제되며, 같은 단계에서 env.auth도 비활성화됩니다. 저장된 OAuth 제공자 시크릿도 함께 제거되며 복구할 수 없습니다.
confirm은 프로젝트 이름과 정확히 일치해야 합니다. 일치하지 않으면 호출은 400 confirm_mismatch를 반환하며 아무것도 시작되지 않습니다.
이 작업은 202를 반환하고 몇 분이 걸리는 장시간 실행 작업이며, 요청 본문에 확인 문자열을 담기 때문에 DELETE가 아니라 POST입니다.
operationId deleteDatabase
요청 본문: application/json · DeleteRequest
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 202 | 작업을 시작했습니다 | OperationStarted |
| 400 | 확인 문자열이 프로젝트 이름과 일치하지 않습니다(confirm_mismatch) | Error |
| 403 | — | — |
| 404 | 프로젝트가 존재하지 않거나, 데이터베이스가 아직 생성되지 않았습니다 | Error |
| 409 | 다른 작업이 이미 진행 중입니다(operation_in_progress) | Error |
GET /v1/orgs/{orgSlug}/projects/{projectName}/database/operations/{opId}
복원 또는 삭제의 진행 상황을 지켜봅니다. CLI는 2초마다 폴링하며 phase가 바뀔 때마다 출력합니다.
작업은 경로에 지정된 프로젝트에 속해야 합니다. 다른 프로젝트의 id는 존재하지 않는 것처럼 404를 반환합니다.
member 이상의 권한이 필요합니다.
operationId getDatabaseOperation
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | Operation 상태 | Operation |
| 403 | — | — |
| 404 | 프로젝트에 해당 작업이 없습니다(다른 프로젝트에 속한 작업도 여기에 해당합니다) | Error |
POST /v1/orgs/{orgSlug}/projects/{projectName}/database/operations/{opId}/abort
작업이 되돌릴 수 없는 지점에 도달하기 전에만 가능합니다: evict, restore_generation, delete는 커밋 단계까지 중단할 수 있지만 restore는 중단할 수 없습니다. 중단하면 프로젝트는 active 상태로 돌아가고 terminalCode=aborted가 남습니다.
admin 이상 권한이 필요하며, 작업은 경로에 있는 프로젝트에 속해야 합니다.
operationId abortDatabaseOperation
| 상태 코드 | 설명 | 응답 본문 |
|---|---|---|
| 200 | 일시 중단된 작업의 상태 | Operation |
| 403 | — | — |
| 404 | 프로젝트에 해당 작업이 없습니다 | Error |
| 409 | 되돌릴 수 없는 지점을 지났습니다(not_abortable) — 커밋 후이거나 restore 작업인 경우입니다. | Error |