API 클라이언트 도구
D.Hub REST API는 OpenAPI 3.x 명세를 제공합니다. 표준 HTTP 클라이언트로 호출하거나 명세에서 클라이언트를 생성합니다. 이 페이지에서는 JWT 인증, 페이지 나눔, 오류 응답을 처리하는 예시를 설명합니다.
- D.Hub 계정으로 API 인증에서 JWT 토큰을 발급합니다.
- 사용할 HTTP 클라이언트를 설치합니다.
D.Hub 전용 SDK 패키지는 제공하지 않습니다. HTTP 클라이언트로 직접 호출하거나 OpenAPI 명세에서 클라이언트를 생성합니다.
명령줄 도구
curl
터미널에서 HTTP 요청을 보내고 응답을 확인합니다.
# Bearer 토큰으로 목록 조회
curl -H "Authorization: Bearer ${TOKEN}" \
https://{host}/api/v1/collections
# 항목 생성
curl -X POST https://{host}/api/v1/collections \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"name": "my-collection"}'
# 파일 업로드(multipart, 파일 필드 이름은 files)
curl -X POST https://{host}/api/v1/datasets/${DATASET_ID}/upload \
-H "Authorization: Bearer ${TOKEN}" \
-F "files=@./data.csv"
# jq로 응답 확인
RESP=$(curl -s -H "Authorization: Bearer ${TOKEN}" https://{host}/api/v1/datasets)
echo "$RESP" | jq -r '.[].id'
API 튜토리얼에서 토큰 발급부터 파이프라인 실행까지의 호출 흐름을 확인합니다.
HTTPie
HTTPie는 명령줄에서 필드 기반 문법으로 JSON 요청을 작성합니다.
# 설치
brew install httpie # macOS
pip install httpie # Python 환경
# GET 호출
http GET https://{host}/api/v1/collections \
Authorization:"Bearer ${TOKEN}"
# POST(필드 = key=value, JSON 요청 본문 생성)
http POST https://{host}/api/v1/collections \
Authorization:"Bearer ${TOKEN}" \
name="my-collection" \
description="HTTPie 예제"
Postman과 Insomnia
화면에서 요청을 구성하고 응답을 확인하는 HTTP 클라이언트입니다. D.Hub OpenAPI 명세를 가져오면 엔드포인트 모음을 생성합니다.
- Postman에서 Import → Link를 선택하고
https://{host}/api/v1/openapi.json을 입력합니다. - Environment에
host와token변수를 등록합니다. - 엔드포인트의 Code 탭에서 필요한 언어의 호출 예시를 생성합니다.
화면에서 요청을 탐색하거나 오류를 확인할 때 사용합니다. 자동화에서는 명령줄 도구나 언어별 HTTP 클라이언트를 사용합니다.
언어별 HTTP 클라이언트
Python (requests)
requests.Session에 인증 헤더를 설정하면 여러 요청에서 같은 헤더를 사용합니다.
import requests
class DHubClient:
def __init__(self, host: str, token: str):
self.host = host
self.session = requests.Session()
self.session.headers["Authorization"] = f"Bearer {token}"
def get(self, path, **params):
r = self.session.get(f"{self.host}{path}", params=params)
r.raise_for_status()
return r.json()
def post(self, path, json):
r = self.session.post(f"{self.host}{path}", json=json)
r.raise_for_status()
return r.json()
client = DHubClient("https://{host}", "${TOKEN}")
collection = client.post("/api/v1/collections", {"name": "my-collection"})
print(collection["id"])
다음 예시는 커서를 따라 전체 페이지를 순회합니다.
def list_all(client: DHubClient, path: str, limit: int = 100):
cursor = None
while True:
params = {"limit": limit}
if cursor:
params["cursor"] = cursor
page = client.get(path, **params)
items = page["items"] if isinstance(page, dict) else page
yield from items
cursor = page.get("next_cursor") if isinstance(page, dict) else None
if not cursor:
return
for dataset in list_all(client, "/api/v1/datasets"):
print(dataset["id"], dataset["name"])
JavaScript / Node.js fetch
Node.js 18 이상에서는 내장 fetch를 사용합니다. 브라우저에서 호출하려면 요청 출처가 D.Hub의 CORS_ORIGINS 설정에 포함되어야 합니다.
const headers = {
"Authorization": `Bearer ${TOKEN}`,
"Content-Type": "application/json",
};
// GET 목록
const list = await fetch(`https://${host}/api/v1/collections`, { headers })
.then((r) => r.json());
// POST 생성
const created = await fetch(`https://${host}/api/v1/collections`, {
method: "POST",
headers,
body: JSON.stringify({ name: "my-collection" }),
}).then((r) => r.json());
OpenAPI 클라이언트 생성하기
openapi-generator-cli로 D.Hub OpenAPI 명세에서 언어별 클라이언트를 생성합니다.
# 명세 다운로드(인증이 활성화된 환경에서는 토큰 헤더 필요)
curl -H "Authorization: Bearer ${TOKEN}" \
-o openapi.json https://{host}/api/v1/openapi.json
# Python 클라이언트 생성
npx @openapitools/openapi-generator-cli generate \
-i ./openapi.json \
-g python \
-o ./dhub2-client-python
# TypeScript Axios 클라이언트 생성
npx @openapitools/openapi-generator-cli generate \
-i ./openapi.json \
-g typescript-axios \
-o ./dhub2-client-ts
| 생성기 | 언어 | 비고 |
|---|---|---|
python | Python 3 | urllib3 기반 동기 클라이언트 |
python-pydantic-v1 | Python 3 | Pydantic v1 기반 모델 |
typescript-axios | TypeScript | Axios 기반 클라이언트 |
typescript-fetch | TypeScript | fetch 기반 클라이언트 |
go | Go | net/http 기반 |
java | Java | Maven 프로젝트 생성 지원 |
전체 생성기 목록은 npx @openapitools/openapi-generator-cli list로 확인합니다.
오류 처리
API 오류 응답의 구조는 오류 처리에서 확인합니다.
- 401 / 403: 토큰을 갱신하고 요청에 필요한 권한을 확인합니다.
- 422:
detail배열에서 유효성 검사를 통과하지 못한 필드를 확인합니다. - 500·502·503·504: 호출 특성에 맞는 재시도 횟수와 대기 시간을 정합니다. 다음 예시는 지수 백오프를 적용합니다.
생성 요청처럼 같은 요청을 반복했을 때 결과가 중복될 수 있는 작업은 자동으로 재시도하지 않습니다.
import time
import requests
def with_retry(call, max_retries=3):
retryable_status_codes = {500, 502, 503, 504}
for attempt in range(max_retries + 1):
try:
return call()
except requests.HTTPError as e:
if e.response.status_code in retryable_status_codes and attempt < max_retries:
time.sleep(2 ** attempt)
continue
raise
페이지 나눔, 정렬, 필터링
- 페이지 나눔:
limit과cursor쿼리 매개변수를 사용합니다. 응답의next_cursor를 다음 요청에 전달합니다. 개발자 가이드 개요에서 응답 구조를 확인합니다. - 정렬: 지원하는 엔드포인트에서는
sort쿼리 매개변수를 사용합니다. 내림차순 표기는 해당 엔드포인트의 API 참조에서 확인합니다. - 필터링: 엔드포인트별 쿼리 매개변수는 API 참조의 매개변수에서 확인합니다.