Datalog에 대한 글을 몇 편 써오면서, 한 가지 고민이 계속 머릿속을 맴돕니다. “Datalog는 정말 일상적으로 쓸 수 있는 도구인가?”라는 질문입니다.

특수한 도메인에서는 빛나지만

Datalog의 활용 사례를 찾으면 대부분 ‘특수한 도메인’에 집중되어 있습니다.

  • 정적 프로그램 분석: 포인터 분석이나 데이터 흐름 분석에서 Datalog는 이미 검증된 도구입니다. Soufflé 같은 고성능 Datalog 엔진은 아예 이 용도에 최적화되어 있습니다.
  • 보안 정책 검증: 접근 제어 규칙을 사실과 규칙으로 표현하고, 의도하지 않은 권한 경로가 존재하는지 추론하는 데 탁월합니다.
  • 네트워크 구성 분석: 라우팅 테이블의 도달가능성을 재귀적으로 계산하는 것은 Datalog의 전형적인 적용 사례입니다.
  • 온톨로지 추론: 지식 그래프 위에서 RDFS/OWL 규칙을 적용하여 암묵적 관계를 도출하는 데 사용됩니다.

이런 예제들은 만들기 어렵지 않습니다. 도메인 자체가 “사실과 규칙으로부터 새로운 사실을 도출한다”는 Datalog의 본질과 정확히 맞아떨어지기 때문입니다. 문제는 이런 사례들을 보여주면 돌아오는 반응이 늘 비슷하다는 점입니다.

“저는 컴파일러도 안 만들고, 보안 정책도 안 다루는데, 이걸 언제 쓰나요?”

이 질문에 선뜻 대답하기가 어렵습니다.

일상적 유즈케이스가 떠오르지 않는 이유

곰곰이 생각해보면, Datalog의 일상적 유즈케이스를 만들기 어려운 데는 구조적인 이유가 있습니다.

첫째, 일상의 데이터 문제는 대부분 SQL로 충분합니다. 테이블에서 조건에 맞는 행을 필터링하고, 집계하고, 조인하는 것—이것이 우리가 매일 하는 ‘데이터 작업’의 대부분입니다. SQL은 이 영역에서 반세기 넘게 검증된 도구이고, 생태계도 압도적입니다.

둘째, 재귀적 추론이 필요한 일상적 상황이 드뭅니다. Datalog가 SQL에 대해 가지는 가장 명확한 이점은 재귀(recursion)입니다. “조상의 조상”이나 “친구의 친구”를 재귀적으로 탐색하는 것은 Datalog의 강점이지만, 일상적인 데이터 작업에서 이런 패턴이 얼마나 자주 등장할까요? SQL의 WITH RECURSIVE가 어색하기는 하지만, 그마저도 필요한 상황 자체가 흔치 않습니다.

셋째, 도구의 접근성 문제가 있습니다. Python에서 Pandas 한 줄이면 해결되는 일에 Datalog 엔진을 별도로 설치하고 사실을 정의하고 규칙을 작성하는 것은 상당한 인지적 전환 비용을 수반합니다. 도구가 주는 가치가 전환 비용을 넘어서지 못하면 채택은 일어나지 않습니다.

그럼에도 가능성이 보이는 영역들

그래도 Datalog가 일상의 도구로 가치를 가질 수 있는 지점이 전혀 없는 것은 아닙니다. 최근에 떠올린 몇 가지 방향을 정리해봅니다.

1. 개인 지식 관리 (Personal Knowledge Management)

Obsidian이나 Logseq 같은 도구를 쓰면서 노트 사이의 관계를 [[링크]]로 연결하는 사람이 늘고 있습니다. 이 링크 그래프는 본질적으로 사실(Facts)의 집합입니다.

references("Datalog 소개", "논리 프로그래밍").
references("논리 프로그래밍", "Prolog").
tagged("Datalog 소개", "datalog").
tagged("논리 프로그래밍", "logic").

% 간접적으로 관련된 노트 찾기
related(X, Y) :- references(X, Y).
related(X, Y) :- references(X, Z), related(Z, Y).

% 같은 태그를 공유하는 노트 클러스터
cluster(X, Y) :- tagged(X, T), tagged(Y, T), X \= Y.

“이 노트와 간접적으로 연결된 노트가 뭐지?”, “내가 놓치고 있는 연결 고리가 있을까?”—이런 질문에 Datalog는 SQL보다 자연스러운 표현력을 제공합니다. 특히 노트가 수백 개를 넘어가면, 단순한 링크 그래프를 넘어 추론 기반의 지식 탐색이 의미를 가지기 시작합니다.

2. 의존성과 영향 분석

소프트웨어 프로젝트의 의존성 관리는 개발자의 일상입니다. 패키지 A가 B에 의존하고, B가 C에 의존할 때, C에 보안 취약점이 발견되면 영향받는 모든 패키지를 찾아야 합니다.

depends_on("my-app", "web-framework").
depends_on("web-framework", "http-lib").
depends_on("http-lib", "openssl").
vulnerable("openssl").

% 전이적 의존성
transitive_dep(X, Y) :- depends_on(X, Y).
transitive_dep(X, Y) :- depends_on(X, Z), transitive_dep(Z, Y).

% 취약한 패키지에 간접적으로 의존하는 모든 패키지
at_risk(X) :- transitive_dep(X, Y), vulnerable(Y).

물론 npm audit이나 pip-audit 같은 전용 도구가 이미 존재합니다. 하지만 Datalog의 장점은 규칙을 자유롭게 조합할 수 있다는 점에 있습니다. “이 모듈을 수정하면 영향받는 테스트는?”, “이 설정을 변경하면 어떤 서비스가 재시작되어야 하는가?”—이런 질문들은 모두 전이적 관계(transitive relation) 위에서의 도달가능성(reachability) 문제이고, Datalog는 이를 선언적으로 표현하는 데 최적화된 언어입니다.

3. 접근 권한의 선언적 관리

RBAC(Role-Based Access Control)은 어디에나 있습니다. 사내 시스템, 클라우드 인프라, 심지어 Google Drive의 공유 설정까지. 문제는 권한이 중첩되고 상속될 때 “이 사람이 이 리소스에 접근할 수 있는가?”라는 질문에 답하기가 점점 어려워진다는 것입니다.

role("김과장", "팀장").
role("이대리", "개발자").
inherits("팀장", "개발자").
permission("개발자", "코드저장소", "read").
permission("팀장", "코드저장소", "write").

% 역할 상속
has_role(User, Role) :- role(User, Role).
has_role(User, Role) :- role(User, R), inherits(R, Role).

% 최종 권한 계산
can_access(User, Resource, Action) :-
    has_role(User, Role),
    permission(Role, Resource, Action).

can_access("김과장", "코드저장소", "read")가 참인지를 확인하는 것은 단순한 조회가 아니라 추론입니다. 팀장 역할이 개발자 역할을 상속하고, 개발자에게 read 권한이 있으므로 김과장도 read 권한을 가집니다. 역할 계층이 깊어지고 조건이 복잡해질수록, 이런 추론을 SQL의 다중 조인으로 표현하는 것은 점점 고통스러워집니다. 실제로 Google의 Zanzibar나 Oso 같은 권한 관리 시스템이 내부적으로 Datalog 혹은 그와 유사한 추론 엔진을 채택한 것은 우연이 아닙니다.

4. 설정과 규칙의 검증

인프라 설정(Infrastructure as Code)이 복잡해지면, 설정 간의 일관성을 검증하는 것이 중요해집니다. “프로덕션 DB는 반드시 암호화가 활성화되어야 한다”, “외부에 노출된 서비스는 인증 미들웨어를 거쳐야 한다”—이런 정책을 Datalog 규칙으로 표현하고, 현재 설정(Facts)에 대해 위반 여부를 검증할 수 있습니다.

service("api-gateway", "external").
service("internal-api", "internal").
has_auth("api-gateway").

% 정책: 외부 서비스는 반드시 인증이 있어야 한다
violation(S) :- service(S, "external"), \+ has_auth(S).

OPA(Open Policy Agent)의 Rego 언어가 이미 이 영역에서 자리 잡고 있지만, Rego의 설계 자체가 Datalog의 영향을 강하게 받았습니다. 이는 “정책은 사실과 규칙의 문제”라는 Datalog의 세계관이 이 영역과 자연스럽게 맞아떨어진다는 것을 방증합니다.

Datalog가 일상의 도구가 되려면

이런 가능성에도 불구하고, Datalog가 일상의 도구로 자리 잡기 위해서는 여전히 넘어야 할 벽이 있습니다.

생태계와 통합의 문제입니다. SQL이 강력한 이유는 언어 자체의 표현력보다 PostgreSQL, MySQL 같은 성숙한 DBMS 생태계, 수십 년간 축적된 라이브러리, 그리고 모든 프로그래밍 언어에서의 네이티브 지원 때문입니다. Datalog에도 Soufflé, Differential Datalog, Naga 같은 구현체가 있지만, “pip install 하고 바로 쓴다”는 수준의 접근성에는 아직 거리가 있습니다.

결국 Datalog가 일상에 스며들려면, 그 자체로 독립적인 도구가 아니라 기존 워크플로우에 자연스럽게 녹아드는 형태가 되어야 할 것 같습니다. Rego가 Kubernetes 생태계에 녹아든 것처럼, 혹은 SQLite가 “서버 없는 임베디드 DB”로 어디에나 쓰이게 된 것처럼. 가벼운 임베디드 Datalog 엔진이 Python이나 JavaScript 한 줄로 호출되고, 일상적인 의존성 분석이나 권한 검증에 자연스럽게 사용되는 모습—그것이 Datalog가 일상의 도구가 되는 경로일 것입니다.

마치며

Datalog의 일상적 유즈케이스를 고민하면서 깨달은 것은, 이 질문 자체가 “이 도구는 누구를 위한 것인가”에 대한 근본적인 물음이라는 점입니다.

특수한 도메인에서 Datalog의 가치는 이미 증명되어 있습니다. 정적 분석, 보안, 네트워크—이 영역에서 Datalog를 대체할 도구를 찾기는 어렵습니다. 그러나 “일반적인 일상”이라는 맥락에서 Datalog는 아직 자신의 자리를 찾고 있는 중입니다.

어쩌면 Datalog의 진짜 일상적 유즈케이스는, 우리가 아직 “이건 Datalog 문제야”라고 인식하지 못하는 곳에 이미 숨어 있을지도 모릅니다. 의존성 트리를 따라가고, 권한 상속을 추적하고, 설정의 정합성을 검증하는 일—이 모든 것이 사실 “사실과 규칙으로부터 결론을 도출하는” 문제이니까요.

다음에는 이 고민을 코드로 풀어보겠습니다. 실제로 가벼운 Datalog 엔진을 일상적인 문제에 적용해보는 실험을 해볼 생각입니다.


관련 글