수정 (2026-05-13): 원래는 온톨로지 교육 맥락에서 쓴 글이었는데, LLM과 함께 Datalog를 쓰다 보니 같은 문제가 다른 형태로 반복된다는 생각이 들었습니다. 그래서 “왜 Datalog인가” 섹션을 덧붙였습니다.

온톨로지나 시맨틱 웹 세미나에서 SPARQL 문법을 처음 보여주면 개발자들은 보통 반가워합니다. SELECT, WHERE, ORDER BY가 그대로 나오니 “조인 많은 SQL이네요”라는 말이 바로 나옵니다. 그런데 이 익숙함이 생각보다 빨리 오해로 바뀝니다.

SPARQL이 SQL과 같지 않은 지점

차이는 문법보다 전제에 있습니다.

SQL은 닫힌 세계 가설(closed world assumption)을 바탕으로 하고 있습니다. 테이블에 없는 정보는 기본적으로 거짓으로 봅니다. 수강생 목록에 ‘홍길동’이 없다면 시스템은 “홍길동은 수강생이 아니다”라고 판단합니다.

SPARQL과 RDF는 반대로 열린 세계 가설(open world assumption)에 가깝습니다. 데이터에 정보가 없다고 해서 그 정보가 거짓이라는 뜻은 아닙니다. “홍길동이 수강생이라는 트리플이 없다”는 것은 “홍길동은 수강생이 아니다”가 아니라 “아직 모른다”에 가깝습니다. 다른 데이터셋에 그 트리플이 있을 수도 있고, 아직 기록하지 않았을 수도 있으니까요.

테이블이냐 그래프냐 하는 구조의 차이보다, 이 전제의 차이가 쿼리 결과와 추론의 방향을 더 크게 바꿉니다. 그런데 SQL과 닮은 구문이 눈앞에 있으면, 학습자는 자신도 모르게 RDB의 멘탈 모델을 SPARQL에 그대로 가져옵니다. OPTIONAL의 동작이나 추론 규칙(entailment regime)이 섞이기 시작하면 “왜 SQL처럼 결과가 안 나오지?”라는 질문이 반복됩니다. 익숙한 문법이 여기서는 방해가 됩니다.

차라리 완전히 다른 문법이라면

그래서 가끔은 온톨로지를 다루는 언어가 SQL과 아예 다르게 생긴 편이 낫겠다고 생각합니다. RDB와 다른 사고방식이 필요하다는 걸 설명하려면, 문법부터 달라야 “이건 SQL이 아니구나”라는 스위치가 켜집니다.

그런 용도로 강연 앞부분에 한 번 놓아보고 싶은 것이 Datalog입니다.

Datalog: 사실과 규칙으로 추론하기

Datalog는 Prolog의 부분집합에서 출발한 선언형 논리 질의 언어입니다. 이름 그대로 데이터와 논리를 엮는 쪽에 초점이 있습니다.

SPARQL이 저장된 트리플을 조회하는 쪽에 가깝다면, Datalog는 사실(facts)과 규칙(rules)에서 새로운 사실을 끌어내는 쪽에 더 가깝습니다. 온톨로지에서 하고 싶은 일이 결국 “이미 적어둔 지식으로부터 모르는 것을 끌어내는 것”이라면, Datalog의 동작 방식은 꽤 잘 맞습니다.

맛보기: 조상 관계

“조상의 조상은 조상이다” 같은 재귀 관계를 SPARQL로 풀어내려면 SPARQL 1.1의 property path를 써야 합니다. 경로 표현에도 제약이 있습니다. Datalog에서는 두 줄이면 됩니다.

ancestor(X, Y) :- parent(X, Y).
ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).
  • 첫 줄: X가 Y의 부모라면, X는 Y의 조상이다.
  • 둘째 줄: X가 Z의 부모이고, Z가 Y의 조상이라면, X도 Y의 조상이다.

문법에 SELECTWHERE도 없습니다. RDB 사고방식을 내려놓아야 읽히는 문법입니다. 그래서 “사실과 규칙으로부터 새 사실을 도출한다”는 쪽으로 생각을 옮기기 쉽습니다.

세 언어를 나란히 놓고 보면

  SQL SPARQL Datalog
데이터 모델 관계형 테이블 RDF 그래프 사실 + 규칙
기본 전제 닫힌 세계 열린 세계 논리적 귀결
핵심 연산 관계 대수 그래프 패턴 매칭 재귀적 추론
주된 쓰임 데이터 관리와 조회 웹 데이터 연결과 탐색 지식 표현과 새 사실 도출

현실의 시맨틱 웹 표준이 SPARQL이라는 사실은 바뀌지 않습니다. 다만 입문 단계에서 SPARQL부터 보여주면 SQL과 너무 닮아 보여서, 온톨로지가 가진 “추론 엔진”으로서의 성격이 잘 드러나지 않을 때가 많습니다. 그 유사성을 먼저 걷어내는 용도로, 또는 이미 SPARQL 문법에서 한 번 헤맨 분들에게 접근 각도를 바꿔주는 도구로, Datalog를 앞에 꺼내볼 만하다고 생각합니다.

Datalog가 LLM과 잘 맞는 이유

이 글을 처음 썼을 때는 Datalog를 주로 교육용 우회로처럼 생각했습니다. 그런데 LLM과 같이 써보면, 같은 이유가 실무적인 장점으로도 이어진다는 걸 자주 느낍니다.

LLM에게 비정형 텍스트에서 지식을 추출하게 시키면, 모델이 사실(fact)과 스키마 설계를 동시에 해버리는 일이 자주 생깁니다. “홍길동은 한국에서 태어났다”를 넣으면 Person, Place, bornIn을 스스로 정의하고 인스턴스까지 채워 넣습니다. 이때 스키마를 즉석에서 만드는 과정에 환각이 섞입니다.

이 역할을 나누기에는 Datalog가 꽤 편합니다.

문법이 단순합니다. predicate(arg1, arg2). 형태로 끝납니다. XML이나 JSON-LD처럼 중첩 구조가 없고, OWL/Turtle처럼 네임스페이스와 prefix 선언도 없습니다. LLM이 형식을 지키기 쉽고, 파싱과 검증도 단순합니다. 모델이 만든 텍스트에서 predicate 이름 하나만 꺼내도 스키마와 대조할 수 있습니다.

역할 구분이 문법에 그대로 남습니다. Datalog는 사실(facts)과 규칙(rules)을 나눠서 씁니다. TBox를 규칙으로 미리 정의해 두고, LLM에게는 facts만 생성하게 할 수 있습니다. 모델이 스키마를 건드릴 여지가 줄어듭니다.

재귀 추론을 선언적으로 적을 수 있습니다. 위에서 본 조상 관계 예시처럼, ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y). 두 줄이면 됩니다. 추출된 facts 위에서 TBox 규칙으로 새 사실을 도출하는 과정도 간결합니다. LLM이 추론까지 담당하면 근거를 추적하기 어렵지만, 이 구성에서는 추론 결과의 출처가 규칙으로 남습니다.

결국 Datalog가 LLM과 잘 맞는 이유는 단순하다는 데 있습니다. 표현력을 일부 포기하는 대신, 모델이 만든 출력이 스키마 안에 있는지 없는지를 코드로 확인하기 쉬워집니다. predicate(arg1, arg2). 하나하나가 독립된 검증 단위가 되고, 스키마 밖의 predicate는 파싱 단계에서 바로 걸러낼 수 있습니다. 표현이 복잡할수록 모호해지는 경계가, 단순한 문법 덕분에 비교적 선명하게 남습니다.


관련 글