OpenAPI 사이트 간 데이터 조회¶
이 문서에서는 query_data를 통해 현재 워크스페이스에서 조회 권한을 부여받은 다른 사이트의 데이터를 조회하는 방법과 비동기 인터페이스가 반환하는 async_id를 올바르게 처리하는 방법을 설명합니다.
적용 인터페이스¶
| 시나리오 | 인터페이스 | 설명 |
|---|---|---|
| 동기 조회(권장) | POST /api/v1/df/query_data_v1 |
신규 연동 시 우선 사용 |
| 비동기 조회 | POST /api/v1/df/asynchronous/query_data |
작업이 계속 실행 중일 때만 async_id 반환 |
| 구버전 호환 | GET/POST /api/v1/df/query_data |
GET은 body=<URL 인코딩된 JSON> 사용, 신규 연동에는 비권장 |
| 조회 권한 대상 조회 | GET /api/v1/wksp_share/granted_ws_list |
대상 workspaceUUID 및 targetRegion 획득 |
| 사이트 구성 조회 | GET /api/v1/workspace/website/list |
사이트 등록 정보 확인 용도이며 데이터 조회 권한을 의미하지 않음 |
External API의 POST /api/v1/df/{workspace_uuid}/query_data는 동기 진입점이며 async_id를 받지 않습니다. 내부적으로는 동일한 DQL 조회 필드를 사용하지만 인증 방식은 External API의 AK/SK 서명입니다.
요청 모델 및 제한 사항¶
사이트 간 조회는 여전히 현재 사이트의 OpenAPI Endpoint를 호출하며 현재 워크스페이스의 DF-API-KEY를 사용합니다. 대상 사이트를 직접 요청할 필요가 없으며 대상 사이트의 Endpoint로 현재 Endpoint를 대체해서도 안 됩니다.
각 queries[i]의 구조는 다음과 같습니다.
{
"qtype": "dql",
"query": {
"q": "L::re(`.*`):(`message`)",
"workspaceUUIDs": ["wksp_target"],
"targetRegion": "region_code"
}
}
다음 규칙을 준수해야 합니다.
- 비어 있지 않은
workspaceUUIDs가workspaceUUID보다 우선합니다.workspaceUUIDs가 빈 배열이거나null이면workspaceUUID로 폴백합니다. 두 필드를 동시에 전달하지 않는 것이 좋습니다. 둘 다 전달하지 않으면 현재 워크스페이스를 조회합니다. - 사이트 간 조회 시 각 query의
query객체 내부에 동일한targetRegion을 명시적으로 전달해야 하며 요청 최상위에만 전달해서는 안 됩니다. - 하나의 요청에 포함된 모든
queries[*]는 하나의 사이트만 가리켜야 합니다. 여러 사이트는 반드시 여러 요청으로 분리한 다음 클라이언트가 결과를 병합해야 합니다. workspaceUUIDs: ["*"]또는workspaceUUID: "*"는 지정된targetRegion내에서 현재 워크스페이스가 조회할 수 있는 모든 권한 부여 워크스페이스를 조회함을 의미합니다. 이 경우targetRegion은 필수입니다.targetRegion은 권한을 부여한 워크스페이스가 속한 사이트의regionCode이며toRegionCode가 아닙니다.- 동일한 요청 내의 여러 대상 워크스페이스는 반드시 동일한
targetRegion에 속해야 합니다. 대상 워크스페이스를 사이트별로 그룹화한 후 요청을 구성하는 것이 좋습니다.
시간 범위 및 페이지네이션 커서¶
query.timeRange의 시작 및 종료 시간은 동일한 단위(초, 밀리초, 마이크로초 또는 나노초)를 사용해야 합니다. 단위를 혼용하면 HTTP 400, ft.TimeRangeUnitMismatch가 반환되며 서버가 자동으로 수정하지 않습니다. 이 문서의 요청 예시는 밀리초를 사용하므로 실제 조회 시간 범위로 교체하십시오.
cursor_time, cursor_token 등의 페이지네이션 파라미터는 조회 시간 범위와 독립적입니다. 페이지를 넘길 때 인터페이스 규약에 따라 응답 커서를 그대로 다시 전달하고 원래 조회의 timeRange는 유지하십시오. 자릿수를 통일하기 위해 커서를 변환하지 마십시오.
대상 워크스페이스 및 targetRegion 획득¶
호출:
curl '<Endpoint>/api/v1/wksp_share/granted_ws_list?namespace=logging&pageIndex=1&pageSize=100' \
-H 'DF-API-KEY: <DF-API-KEY>' \
--compressed
namespace로 데이터 유형별로 권한을 필터링할 수 있습니다. 예:
- 로그:
logging - 분산 추적:
tracing - 메트릭:
metric - RUM:
rum - 신서틱 모니터링:
dialtest
응답은 권한을 부여한 사이트별로 그룹화됩니다.
{
"code": 200,
"content": [
{
"regionCode": "region_a",
"regionName": "站点 A",
"data": [
{
"workspaceUUID": "wksp_target_a",
"workspaceName": "目标工作空间 A",
"regionCode": "region_a",
"toWorkspaceUUID": "wksp_current",
"toRegionCode": "region_current",
"type": ["logging"],
"indexes": ["*"]
}
],
"pageInfo": {
"pageIndex": 1,
"pageSize": 100,
"totalCount": 1
}
}
],
"success": true
}
파라미터를 구성할 때:
data[*].workspaceUUID를query.workspaceUUID또는query.workspaceUUIDs의 값으로 사용합니다.- 해당 워크스페이스가 속한 그룹의
content[*].regionCode(또는 동일 데이터 항목의regionCode)를query.targetRegion으로 사용합니다. toWorkspaceUUID는 조회 대상으로 사용하지 마십시오. 일반적으로 현재 API Key가 속한 권한 부여 대상 워크스페이스입니다.toRegionCode를targetRegion으로 사용하지 마십시오. 일반적으로 현재 사이트입니다.granted_ws_list는 사이트 그룹별로 독립적으로 페이지네이션되며pageInfo.count는 현재 페이지의 수량일 뿐이므로 이를totalCount와 직접 비교하여 페이지 번호를 무한정 증가시키면 안 됩니다.- 처음에는
regionCode를 전달하지 않고pageIndex=1&pageSize=100으로 권한 부여 사이트를 확인한 다음, 조회가 필요한 각 사이트에 해당regionCode를 명시적으로 전달하고 각각 1페이지부터 페이지를 넘깁니다. - 특정 사이트에서 누적 획득한 고유 권한 수가 해당 그룹의
pageInfo.totalCount에 도달하거나pageIndex * pageSize >= totalCount가 되면 중지합니다. 페이지 데이터를 병합할 때 권한 레코드uuid로 중복을 제거하고(regionCode, workspaceUUID)로 대상 매핑을 검증합니다. 동일한 매핑에 충돌하는 권한이 있는 경우 권한 범위를 임의로 확장하지 마십시오.
예를 들어 region_a의 2페이지만 조회하려면:
curl '<Endpoint>/api/v1/wksp_share/granted_ws_list?namespace=logging®ionCode=region_a&pageIndex=2&pageSize=100' \
-H 'DF-API-KEY: <DF-API-KEY>' \
--compressed
GET /api/v1/workspace/website/list가 반환하는 content[*].regionCode는 사이트 코드 후보로만 사용할 수 있습니다. 특정 사이트가 사이트 목록에 존재한다고 해서 현재 워크스페이스가 해당 사이트의 데이터 조회 권한을 획득했다는 의미는 아닙니다. 최종적으로는 granted_ws_list의 결과를 기준으로 해야 합니다.
동기 사이트 간 조회¶
다음 예시는 region_a 사이트의 wksp_target_a를 조회합니다.
curl '<Endpoint>/api/v1/df/query_data_v1' \
-H 'Content-Type: application/json' \
-H 'DF-API-KEY: <DF-API-KEY>' \
--data-raw '{
"queries": [
{
"qtype": "dql",
"query": {
"q": "L::re(`.*`):(`message`)",
"timeRange": [1772516130000, 1772519730000],
"limit": 100,
"workspaceUUIDs": ["wksp_target_a"],
"targetRegion": "region_a"
}
}
]
}' \
--compressed
특정 사이트 내 모든 권한이 부여된 워크스페이스를 조회하려면:
{
"queries": [
{
"qtype": "dql",
"query": {
"q": "L::re(`.*`):(`message`)",
"timeRange": [1772516130000, 1772519730000],
"limit": 100,
"workspaceUUIDs": ["*"],
"targetRegion": "region_a"
}
}
]
}
region_a와 region_b를 동시에 조회해야 하는 경우 각각 별도의 요청 두 번을 보내야 합니다.
동일한 queries 배열에 서로 다른 targetRegion을 혼용하지 마십시오. 그렇지 않으면 인터페이스가 ft.UnsupportMultiSiteQuery를 반환합니다.
비동기 조회 및 async_id 수명 주기¶
async_id는 단일 조회 작업의 핸들이며 세션 ID, 고정 클라이언트 ID 또는 페이지네이션 커서가 아닙니다. 새 조회에는 절대 이전 async_id를 포함해서는 안 됩니다.
1. 최초 제출: async_id 생략¶
curl '<Endpoint>/api/v1/df/asynchronous/query_data' \
-H 'Content-Type: application/json' \
-H 'DF-API-KEY: <DF-API-KEY>' \
--data-raw '{
"queries": [
{
"qtype": "dql",
"query": {
"q": "L::re(`.*`):(`message`)",
"timeRange": [1772516130000, 1772519730000],
"limit": 100,
"workspaceUUIDs": ["wksp_target_a"],
"targetRegion": "region_a"
}
}
]
}' \
--compressed
작업이 계속 실행 중인 경우 응답 예시:
{
"code": 200,
"content": {
"data": [
{
"async_id": "async_task_001",
"is_running": true
}
]
},
"success": true,
"traceId": "TRACE-XXXX"
}
2. 폴링: 실행 중인 작업 ID만 다시 전달¶
동일한 결과 항목이 다음 조건을 모두 충족할 때만 폴링합니다.
ID를 동일한 배열 인덱스의 queries[i].async_id에 다시 넣고 qtype, query.q, 시간 범위, 대상 워크스페이스 및 targetRegion은 변경하지 않은 채 유지합니다.
{
"queries": [
{
"async_id": "async_task_001",
"qtype": "dql",
"query": {
"q": "L::re(`.*`):(`message`)",
"timeRange": [1772516130000, 1772519730000],
"limit": 100,
"workspaceUUIDs": ["wksp_target_a"],
"targetRegion": "region_a"
}
}
]
}
증분 백오프를 사용하고 전체 타임아웃을 설정하는 것이 좋습니다. 예를 들어 먼저 1초를 기다린 후 2초, 4초로 점차 늘리는 방식입니다. 간격 없이 연속으로 요청하지 마십시오.
3. 종료: async_id 포함 중단¶
content.data[i].is_running이 false이면 해당 작업은 이미 종료된 것입니다. 호출자는 최종 데이터를 읽고 즉시 폴링을 중지해야 합니다. 응답 객체에 async_id 필드가 여전히 포함되어 있는지 여부와 관계없이 다음 새 조회에서는 반드시 이전 ID를 생략해야 합니다.
다음과 같은 동작은 잘못되었습니다.
- 이전 작업의
async_id를 모든 후속 요청에 고정으로 포함하는 경우. - DQL, 시간 범위, 워크스페이스 또는
targetRegion을 수정한 후에도 이전 ID를 계속 재사용하는 경우. content.data[0].async_id를queries[1]에 넣는 경우.async_id로search_after,cursor_time또는cursor_token을 대신하여 페이지를 넘기는 경우.
is_running=true인데 async_id가 비어 있는 경우 로컬에 저장된 이전 ID를 다시 채우지 마십시오. 응답의 traceId를 기록하고 제한된 재시도 정책에 따라 해당 논리 조회를 다시 요청하십시오. 이 현상이 지속되면 기술 지원에 문의하십시오.
배치 비동기 조회에서 content.data[i]와 queries[i]는 배열 인덱스로 서로 대응됩니다. ID와 조회 항목이 잘못 매칭될 위험을 줄이기 위해 비동기 호출 시 매번 하나의 query만 제출하는 것을 권장합니다.
페이지네이션과 비동기 작업의 차이¶
비동기 작업이 완료된 후에도 페이지네이션은 최종 조회 결과가 반환한 페이지네이션 필드를 사용합니다.
| 시나리오 | 다음 요청 파라미터 |
|---|---|
| 로그 심층 페이지네이션 | 응답의 search_after를 다음 조회의 query.search_after에 전달 |
| 시간 분할 조회 | 최초에 query.cursor_time을 종료 시간으로 설정하고 이후에는 응답의 next_cursor_time 전달 |
| 동일 타임스탬프 안전 페이지 전환 | 응답의 next_cursor_token을 다음 조회의 query.cursor_token에 전달 |
페이지 전환은 새로운 조회 요청이므로 완료된 작업의 async_id를 계속 포함해서는 안 됩니다. 페이지 전환 요청이 다시 비동기 작업으로 전환되더라도 'async_id 생략'부터 새로운 수명 주기를 시작합니다.
클라이언트 병합 권장 사항¶
서버는 한 번의 query_data 요청에서 여러 사이트를 걸친 조회를 지원하지 않습니다. 클라이언트에서 병합할 때 다음 사항을 권장합니다.
- 먼저
targetRegion별로 대상 워크스페이스를 그룹화합니다. - 각 사이트별로 요청, 페이지네이션, 비동기 작업 처리를 각각 독립적으로 수행합니다.
- 각 배치 결과에
sourceRegion,queriedWorkspaceUUIDs등의 클라이언트 메타데이터를 추가합니다. 다중 워크스페이스 조회는 모든 레코드에 신뢰할 수 있는 출처 워크스페이스가 포함된다는 것을 보장하지 않으므로 전체 배치 결과를 특정sourceWorkspaceUUID로 표시할 수 없습니다. 한 번에 하나의 워크스페이스만 조회하는 경우에만 이렇게 표시할 수 있습니다. 레코드 수준의 출처가 필요한 경우 워크스페이스별로 조회하거나 DQL이 업무상 확인된 신뢰할 수 있는 출처 차원을 반환하도록 해야 합니다. - 로그 유형 결과는
time,date_ns및 안정적인 고유 식별자를 기준으로 정렬하고 중복을 제거합니다. 메트릭 결과는 시간 입도, 집계 함수, 태그 집합이 일치하는지 먼저 확인한 후 병합해야 합니다. - 특정 사이트가 실패하면 다른 사이트의 성공 결과를 보존하고 사이트별 오류 상세를 반환해야 합니다. 부분 성공을 전체 성공으로 포장하지 마십시오.
일반적인 오류¶
| 오류 코드 / 현상 | 원인 | 처리 방법 |
|---|---|---|
ft.TimeRangeUnitMismatch |
timeRange 시작/종료 시간에 서로 다른 단위를 혼용함 |
동일한 단위로 시간 범위를 다시 구성하고 페이지네이션 커서는 응답 그대로 다시 전달 |
ft.UnsupportMultiSiteQuery |
하나의 요청에 여러 대상 사이트를 혼합함 | targetRegion별로 요청 분리 |
ft.workspaceUnauthorized |
대상 워크스페이스가 현재 워크스페이스에 권한이 부여되지 않음 | granted_ws_list를 다시 조회하여 권한 상태와 UUID 확인 |
ft.NotFoundWorkspaceAuthorizationCfg |
대상 사이트에 사용 가능한 권한 구성이 없음. *를 사용했지만 사이트에 권한이 없는 경우에 흔함 |
targetRegion 확인 및 대상 사이트에 유효한 권한 존재 여부 확인 |
ft.NoInitOtherNodeCfg |
외부 조직 사이트 간 권한은 존재하지만 대상 사이트의 Front Endpoint/노드 구성이 없음 | 무작정 재시도하지 말고 사이트 관리자에게 문의하여 대상 노드 구성을 확인하고 보완 |
ft.InvalidWorkspace |
현재 사이트의 대상 워크스페이스가 유효하지 않거나 비활성화됨 | 워크스페이스 목록을 새로 고치고 상태 확인 |
| 계속 이전 결과를 폴링함 | 클라이언트가 완료된 작업의 async_id를 장기간 재사용함 |
is_running=false 이후 로컬 ID를 삭제하고 새 조회에는 async_id를 전달하지 않음 |
| 사이트는 존재하지만 데이터를 조회할 수 없음 | workspace/website/list만 확인하고 권한을 확인하지 않음 |
wksp_share/granted_ws_list를 기준으로 판단 |
DQLDataAccessScopeRestricted warning |
데이터 액세스 규칙이 일부 인덱스만 허용하거나 관련 인덱스를 허용하지 않음 | warnings[].details[].metadata.restriction 및 데이터 액세스 규칙 확인 |
출시 전 점검 목록¶
- 현재 워크스페이스의
DF-API-KEY로 현재 사이트의 OpenAPI Endpoint를 요청합니다. -
granted_ws_list에서 대상workspaceUUID와 동일 그룹의regionCode를 획득합니다. - 모든 사이트 간 query에 동일한
targetRegion을 명시적으로 전달합니다. - 다중 사이트 대상을
targetRegion별로 여러 요청으로 분리했습니다. - 새 비동기 조회에는
async_id를 전달하지 않습니다. -
is_running=true이고 ID가 비어 있지 않은 경우에만 폴링하고 배열 인덱스로 작업을 바인딩합니다. -
is_running=false이후 작업 ID를 삭제합니다. 페이지네이션은 새로운 비동기 수명 주기에서 시작합니다. - 폴링 백오프, 전체 타임아웃, 페이지네이션 상한 및 사이트별 오류 처리를 설정합니다.
- 결과 병합 시 출처 사이트/워크스페이스를 유지하고 업무 기본 키로 중복을 제거합니다.