개념 해설 · 2026-08-16
SPARQL은 데이터를 찾는 언어가 아니라, ontology의 약속을 실행하는 질문이다
확정된 대상과 정책을 검증 가능한 질의와 답변 근거로 바꾸는 실행 경계.
SPARQL을 “그래프 DB용 SQL”로만 이해하면 중요한 부분을 놓친다. SQL이 저장 구조를 따라 데이터를 찾는 언어라면, SPARQL은 ontology가 정한 의미와 관계를 따라 질문하는 언어에 가깝다. 그래서 SPARQL을 잘 쓰려면 문법보다 먼저 “우리 회사에서 고객·주문·장애 티켓은 어떤 개념이며 어떻게 연결되는가”가 합의되어 있어야 한다.
질문은 원본 컬럼이 아니라 의미 경로를 따른다
사용자가 다시 이렇게 묻는다.
지난주 장애 문의가 많았던 A사, 아직 미처리 주문도 있어?
발화 분석과 Knowledge Graph가 A사를 customer:acme-corp로 좁혔고, ontology는 다음을 약속했다고 하자.
Organization ─hasSupportTicket→ SupportTicket
Organization ─hasOrder→ Order
SupportTicket.category = Incident
Order.fulfilmentStatus ∈ {Pending, Processing} = 미처리
이제 질의는 CRM의 company_id, 지원 도구의 tag, ERP의 shipment_flag를 각각 직접 꿰맞추는 대신, 이 의미 경로를 사용한다. 어떤 원천이 바뀌어도 매핑 계층이 ontology의 약속을 지키면 질문의 모양은 유지된다.
작동 예제: 자연어가 SPARQL이 되기 전
정규화된 의미 프레임을 먼저 보자.
organization: customer:acme-corp
interval: 2026-08-03T00:00:00 ~ 2026-08-10T00:00:00
ticket.category: Incident
ticket.count threshold: 5
order.status: unresolved
이 상태에서 만들어지는 질의의 의도는 명확하다. 지난주 incident 티켓을 세고, 같은 조직의 미처리 주문을 함께 가져온다.
PREFIX ex: <https://example.internal/>
SELECT ?org (COUNT(?ticket) AS ?incidentCount)
(COUNT(DISTINCT ?order) AS ?unresolvedOrderCount)
WHERE {
VALUES ?org { ex:customer-acme-corp }
?org ex:hasSupportTicket ?ticket .
?ticket ex:category ex:Incident ; ex:openedAt ?openedAt .
FILTER (?openedAt >= "2026-08-03T00:00:00"^^xsd:dateTime &&
?openedAt < "2026-08-10T00:00:00"^^xsd:dateTime)
OPTIONAL {
?org ex:hasOrder ?order .
?order ex:fulfilmentStatus ?status .
VALUES ?status { ex:Pending ex:Processing }
}
}
GROUP BY ?org
실행 결과가 incidentCount=6, unresolvedOrderCount=2라면, 정책 규칙 “incidentCount가 5 이상”이 참이므로 시스템은 “지난주 장애 문의는 기준 이상이었고, 미처리 주문은 2건입니다”라고 답할 수 있다.
여기서 SPARQL은 자연어를 직접 이해하지 않는다. 앞단에서 확정된 엔터티, 기간, 개념, 상태 범위를 받아 검증 가능한 질문으로 바꾼다. LLM이 이 질의를 보조 생성할 수는 있어도, 실행 전에는 허용된 ontology 경로·필터·집계만 썼는지 검증해야 한다.
SPARQL이 드러내는 설계의 빈칸
이 예제는 동시에 몇 가지 빈칸을 드러낸다. Incident가 지원 도구의 어떤 태그와 매핑되는가? 미처리는 Pending과 Processing만인가? 주문 수를 세는 것과 주문 금액을 합산하는 것은 다른 질문인가? 값이 하나도 없을 때 0으로 답할지, 데이터 미연동으로 답할지?
질의가 잘 작성되지 않는 이유가 SPARQL 문법 부족인 경우는 생각보다 적다. 더 자주 문제인 것은 ontology의 관계가 빠졌거나, 운영 용어의 정의가 합의되지 않았거나, 원천 데이터 품질을 모르는 경우다. 질의 작성은 이런 빈칸을 드러내는 좋은 테스트다.
안전한 실행 경계
운영 시스템에서는 질문을 바로 원본 DB에 쏘기보다 다음 경계를 둔다.
-
발화에서 추출한 값은 후보 상태로 둔다.
-
ontology의 타입·관계·허용 속성으로 후보를 검증한다.
-
정해진 질의 템플릿 또는 허용된 SPARQL 패턴에 값만 채운다.
-
결과와 근거, 사용한 기준을 함께 반환한다.
이 구조면 “어떤 고객을 대상으로, 어떤 상태 범위를, 어떤 기간으로 세었는가”를 답과 함께 설명할 수 있다. 그리고 다음 질문에서 사용자가 “그 주문 상세도 보여줘”라고 하면 이미 확정된 조직·기간·주문 상태를 대화 상태로 재사용할 수 있다.
하지만 모든 빈칸이 데이터로 채워지는 것은 아니다. 후보가 둘이거나 ‘많다’의 기준이 아직 합의되지 않았다면, 가장 좋은 SPARQL은 아직 실행하지 않는 것이다. 그 순간부터 필요한 것은 검색이 아니라 다음 대화의 설계다.
결과는 값만이 아니라 답변의 근거다
실행 계층이 반환해야 할 것은 숫자만이 아니다. 최소한 다음 정보를 결과 객체에 함께 남기는 편이 좋다.
organization: A 주식회사 (customer:acme-corp)
interval: 2026-08-03 ~ 2026-08-09
incidentCount: 6
unresolvedOrderCount: 2
threshold: 5
mappings: Incident, Pending|Processing
source freshness: support=real-time, ERP=15 minutes
이 정보는 사용자가 볼 최종 답변을 장황하게 만들기 위한 것이 아니다. 답변 생성, 감사, 재실행, 예외 처리를 위한 공통 근거다. 예컨대 ERP 연동이 지연됐다면 “주문 데이터는 15분 전 기준”이라고 표시할 수 있다.
SPARQL을 실행 가능한 경계로 두면 권한 통제도 명료해진다. 모델이 임의의 그래프 경로를 탐색하게 하기보다, 사용자 역할에 따라 허용된 질의 템플릿·그래프·속성만 노출한다. 자연어 인터페이스의 편리함이 원천 시스템의 접근 권한을 우회하지 않게 만드는 장치다.