모델과 하드웨어 사이, 비어 있는 계층

Posted on April 10, 2026
모델과 하드웨어 사이, 비어 있는 계층

누구도 책임지지 않는 층위

현대 AI 시스템의 모식도를 그려보면, 보통 두 개의 층만이 뚜렷하게 보입니다. 위에는 모델이 있습니다. 대규모 언어 모델(LLM), 임베딩 모델, 멀티모달 모델, 그리고 그것들을 호출하는 에이전트 프레임워크. 아래에는 하드웨어가 있습니다. GPU, TPU, NPU, 그리고 최근의 Apple Silicon, Qualcomm Hexagon 같은 온디바이스 가속기. 이 두 층은 각각 수천억 달러의 투자와 수많은 논문, 그리고 그 위에서 경쟁하는 스타트업들로 붐비는 곳입니다.

그런데 이 두 층 사이에, 지금 잘 정의되지 않은 하나의 층위가 있습니다. 모델이 실제 사용자 데이터에 접근하기 위해 지나가야 하는 층위. 하드웨어 위에서 데이터를 저장하고 인덱싱하고 질의하는 층위. 전통적으로 "데이터베이스"라고 불러온 계층입니다.

이 층위가 지금 망가져 있습니다. 정확히 말하면, 비어 있지도 않고 제대로 차 있지도 않은 애매한 상태에 있습니다. 데이터센터 쪽에서는 관계형 DB, 전문 검색 엔진, 벡터 DB, 그래프 DB가 각자의 역사적 경로를 따라 발전해온 결과, 현재 AI 애플리케이션은 이 엔진들을 애플리케이션 층의 글루 코드로 엮어서 사용하고 있습니다. 온디바이스 쪽에서는 이 계층이 거의 존재하지 않습니다. 각 앱이 자기 데이터를 개별적으로 관리하고, OS는 권한 모델만 제공하며, 모델은 결국 "주어진 컨텍스트 윈도우"만 봅니다.

이 글은 왜 이 층위가 현재의 모습을 갖게 되었는지, 왜 이것이 "시장이 성숙하면 해결될" 과도기적 현상이 아니라 구조적 문제인지, 그리고 올바른 해법이 갖춰야 할 조건이 무엇인지에 대한 관찰입니다. 글 말미에서 이 조건들에 대한 하나의 구체적 응답으로 UQA와 Cognica 엔진을 제시하지만, 그것은 이 문제 공간의 유일한 답이 아니라 하나의 데이터 포인트일 뿐입니다.

1. 파편화의 역사

현재 우리가 "데이터 인프라"라고 부르는 것은 서로 다른 시대에 서로 다른 문제를 풀기 위해 발전한 엔진들의 집합입니다.

관계형 데이터베이스는 1970년대 기업 업무 데이터 — 재무, 인사, 재고 — 를 위해 Codd의 관계 대수 위에 세워졌습니다. ACID 트랜잭션, 조인, 집계, 정규화된 스키마. 이 패러다임이 50년 동안 "데이터베이스"의 기본값이었습니다.

전문 검색(full-text search)은 1990년대 웹의 등장과 함께 정보 검색 커뮤니티의 수십 년에 걸친 연구가 실용화되면서 별도의 엔진으로 자리잡았습니다. TF-IDF, BM25, 역색인, 포스팅 리스트. Lucene이 2000년대에 표준이 되었고, Elasticsearch가 그 위에 운영 가능성을 얹어 기업 검색의 사실상 표준이 되었습니다. 관계형 DB와는 다른 엔진에서 동작한다는 것이 자명한 사실로 받아들여졌습니다.

벡터 검색은 훨씬 최근입니다. Word2Vec, Transformer, 그리고 대형 언어 모델이 텍스트를 연속 공간의 벡터로 매핑 가능하게 만들면서, "의미적으로 가까운 것 찾기"가 실용적 쿼리가 되었습니다. HNSW, IVF 같은 ANN 알고리즘이 이 공간에서의 빠른 최근접 이웃 검색을 가능하게 했고, Pinecone, Weaviate, Qdrant, Milvus 같은 전용 벡터 DB가 등장했습니다. 2020년대 초중반의 현상입니다.

그래프 데이터베이스는 또 다른 궤적으로 발전했습니다. Neo4j, Apache AGE, TigerGraph 등은 관계가 많은 데이터 — 소셜 그래프, 지식 그래프, 의존성 그래프 — 를 위한 별도의 질의 언어(Cypher, Gremlin, SPARQL)와 저장 구조를 가지고 있습니다.

공간 데이터베이스 역시 별도의 궤적입니다. PostGIS, Oracle Spatial, SpatiaLite 같은 시스템들이 지리 정보 시스템(GIS)의 요구에서 출발해 R-Tree 공간 인덱스, 공간 관계 술어(intersects, within, contains), 거리 함수 같은 전문화된 연산을 제공했습니다. 위치 기반 서비스가 모바일의 기본 기능이 되면서 공간 질의는 일상화되었지만, 다른 패러다임의 엔진과는 여전히 분리되어 있습니다.

이 다섯 패러다임이 각자의 학문적 계보, 구현 전통, 벤더 생태계를 가지고 수십 년에 걸쳐 진화했습니다. 그들이 하나의 시스템 안에서 섞일 이유는 없었습니다. 각 패러다임은 자기가 잘하는 작업의 범위 안에서 최적화되어 있었고, 다른 패러다임의 문제는 그쪽 엔진을 불러와서 해결하면 되는 일이었습니다.

그런데 AI가 이 안정적인 분업 구조를 무너뜨렸습니다.

2. AI 워크로드가 만든 새로운 요구

LLM 기반 애플리케이션이 "실제 데이터에 닿는 순간" 발생하는 질의들을 가만히 들여다보면, 거의 모두가 여러 패러다임을 동시에 요구합니다. 예를 들어보겠습니다.

에이전트가 사용자의 질문을 받고 "내가 지난 주 알렉스와 나눈 대화 중에서, 우리가 3월에 논의했던 프로젝트와 관련된 것들"을 찾아야 한다고 해보겠습니다. 이 한 질의는 다음을 모두 요구합니다:

  • 관계형 필터: 발신자 = 알렉스, 시간 범위 = 지난 7일
  • 전문 검색: "프로젝트" 같은 키워드 매칭
  • 벡터 검색: 3월에 언급된 프로젝트 설명과 의미적으로 가까운 내용
  • 그래프 탐색: "알렉스와 나눈 대화"라는 관계를 따라가는 것
  • 시간적 추론: "3월에 논의했던"이 무엇을 지시하는지 해석

현재의 스택에서 이 질의를 처리하려면 애플리케이션 코드가 다음과 같이 동작합니다. 먼저 관계형 DB에서 지난 주의 알렉스 메시지를 가져옵니다. 그 다음 각 메시지를 벡터 DB에 넣어서 "3월의 프로젝트 설명"과의 유사도를 구합니다. 또한 전문 검색 엔진에 "프로젝트" 관련 키워드 매칭을 던집니다. 이 세 결과를 애플리케이션 메모리에서 조합합니다. 조합하는 방식은 대개 각 엔진의 점수를 임의의 가중치로 합산하는 것입니다.

이 접근의 문제는 표면적 불편함이 아니라 구조적 결함입니다.

첫째, 지연이 선형적으로 누적됩니다. 각 엔진 호출이 네트워크 왕복을 요구하고, 결과 집합이 크면 데이터 전송 자체가 병목이 됩니다. 에이전트 워크플로우가 수십 개의 질의를 연쇄할 경우, 사용자 체감 지연이 수 초에서 수십 초로 늘어납니다.

둘째, 점수 결합이 원리적이지 않습니다. BM25 점수와 코사인 유사도와 PageRank 값은 서로 다른 스케일과 분포를 가집니다. 이들을 0.3 * BM25 + 0.5 * cosine + 0.2 * pagerank 같은 식으로 합산하는 것은 어떤 수학적 정당성도 없는 임시방편입니다. 이 가중치는 대부분 직관과 A/B 테스트로 결정되며, 데이터 분포가 바뀌면 다시 튜닝해야 합니다. 여러 신호의 결합 분포에 대한 원리적 추론은 이런 가중 합산으로는 불가능합니다.

셋째, 저장이 중복됩니다. 같은 문서가 관계형 DB에 한 번, 전문 검색 엔진에 한 번, 벡터 DB에 한 번 저장됩니다. 세 엔진을 동기화하는 것 자체가 별도의 엔지니어링 프로젝트가 되며, 종종 일관성 문제의 원인이 됩니다. 저장 비용은 말 그대로 3배가 됩니다.

넷째, 각 엔진의 옵티마이저가 전역 최적화를 할 수 없습니다. 관계형 DB는 자기 쿼리만 최적화하고, 벡터 DB는 자기 쿼리만 최적화합니다. 애플리케이션 레벨에서 이루어지는 "결합"은 이 개별 최적화의 시야 밖에 있습니다. 그 결과, 정말로 중요한 최적화 — 예컨대 "벡터 검색의 후보를 1000개로 제한한 뒤, 그 중 관계형 필터를 통과한 것만 점수화" 같은 — 가 수동으로 표현되어야 하며, 대부분의 팀이 이것을 제대로 하지 못합니다.

이 네 문제의 공통 원인은 데이터 모델이 애플리케이션 층에서 재조립되고 있다는 것입니다. 그런데 애플리케이션 층은 데이터의 진짜 모양을 알지 못합니다. 그것은 엔진의 일입니다. 데이터의 모양을 모르는 층에서 조합이 일어나면, 조합의 품질은 운에 맡겨집니다.

3. 현재의 "해결책"들이 진짜 해결이 아닌 이유

이 문제가 인지되지 않은 것은 아닙니다. 여러 시도가 있었고, 각각이 부분적 진전을 이뤘습니다. 하지만 어느 것도 구조적으로 문제를 풀지 못합니다.

RAG 프레임워크 (LangChain, LlamaIndex 등). 이것들은 오케스트레이션 레이어이지 저장 레이어가 아닙니다. 여전히 N개의 전문화된 엔진 위에 앉아 있으며, 그 엔진들 사이의 임피던스 미스매치를 모두 상속받습니다. 파이썬 레벨의 글루 코드를 "프레임워크"라고 부르는 것이 이들의 본질입니다. 그리고 온디바이스에서는 거의 쓸 수 없습니다 — 파이썬 런타임이 모바일에 맞지 않고, 여러 엔진을 동시에 돌릴 메모리 여유가 없습니다.

벡터 DB에 텍스트/필터 추가 (Pinecone, Weaviate, Qdrant, Milvus 등). 이들은 벡터 DB로 출발해서 하이브리드 검색을 "기능 확장"으로 붙였습니다. 대수적 기초가 없기 때문에 점수 결합은 여전히 가중 합산입니다. 관계형 능력은 필터 수준을 넘지 못하며, 그래프는 대부분 없습니다. 임베디드를 목표로 설계되지 않았습니다.

관계형 DB에 벡터 추가 (pgvector, MySQL HeatWave, SQL Server 등). 역방향 접근입니다. 진짜 관계형 능력은 있지만, 벡터 기능은 볼트온(bolt-on)입니다. 전문 검색은 보통 예전 방식의 tsquery 수준이며, 현대적인 BM25와 확률적 보정은 거의 없습니다. 대수적 통합은 아닙니다.

Lucene/Elasticsearch + 벡터. 가장 좋은 전문 검색, 꽤 괜찮은 벡터, 관계형 없음, 그래프 없음, 무거운 JVM 풋프린트. 온디바이스는 생각조차 할 수 없습니다.

특화된 "AI 데이터베이스" (LanceDB, Chroma, Marqo 등). 벡터 우선, 나머지는 부차적입니다. 종종 트랜잭션 워크로드를 위한 지속성 보장이 없습니다. 이론적 기반이 얕습니다.

이 모든 시스템의 공통점은, 각자가 기존 패러다임의 국소적 최적점이라는 것입니다. 어느 것도 "AI 시대의 데이터 접근을 위한 올바른 통합 프레임워크는 무엇인가?"라는 질문에서 출발하지 않았습니다. 그들은 이미 존재하는 엔진에 새 기능을 붙였거나, 새 엔진을 만들 때도 한 패러다임을 중심에 두고 나머지를 주변부로 다뤘습니다.

이것이 "시장이 성숙하면 해결될" 문제가 아닌 이유이기도 합니다. 벡터 DB가 충분히 성숙해도 관계형 능력은 부차적인 것으로 남을 것입니다. 관계형 DB가 벡터 기능을 더 정교하게 만들어도 애드혹 점수 결합의 한계는 그대로일 것입니다. 구조적 문제는 시간으로 치유되지 않습니다.

4. 온디바이스: 층위가 아예 없다

지금까지 이야기한 문제들은 데이터센터 쪽에서 일어나는 일입니다. 온디바이스로 가면, 이 층위는 아예 존재하지 않습니다.

현재 iOS/Android 디바이스 위에서 동작하는 AI 기능들 — Apple Intelligence, Gemini Nano, 그리고 각종 앱 내장 모델들 — 을 가만히 들여다보면, 이들 모두가 같은 근본적 한계에 부딪혀 있습니다. 모델은 디바이스에 있지만, 모델이 접근할 수 있는 데이터 레이어는 없습니다.

사용자의 디바이스에는 수년치의 개인 데이터가 쌓여 있습니다. 메시지, 이메일, 문서, 캘린더, 사진 메타데이터, 브라우저 히스토리, 앱 활동 로그, 위치 이력. 이것은 엄청난 양의 컨텍스트이고, 제대로 접근할 수만 있다면 진정으로 개인화된 AI 경험의 토대가 될 수 있습니다. 그런데 현재 아키텍처로는 이 데이터에 통합된 방식으로 접근할 방법이 없습니다.

각 앱이 자기 데이터를 프라이빗 사일로에 저장합니다 — 이는 프라이버시를 위해 의도된 설계이기도 합니다. OS는 권한 모델만 제공하며, 앱 간 데이터 접근은 명시적 인텐트를 통해서만 가능합니다. Spotlight, Core Data, Core Spotlight, App Intents 같은 API들이 각자의 방식으로 일부 통합을 시도하지만, 이들은 "검색"이나 "인텐트 처리" 수준이지 "질의"가 아닙니다. 여러 앱의 데이터에 걸친 벡터 검색? 그래프 탐색? 원리적인 멀티모달 융합? 존재하지 않습니다.

설상가상으로, 모바일 디바이스의 자원 제약은 기존 서버용 솔루션을 그대로 가져오는 것을 불가능하게 만듭니다. Elasticsearch 인스턴스를 폰에 띄울 수는 없습니다. Postgres + pgvector + Neo4j를 동시에 돌릴 배터리가 없습니다. 각 엔진이 독립적으로 메모리 상주 인덱스를 유지하는 설계는 백그라운드 앱이 OS에 의해 강제 회수되는 환경에서 붕괴합니다.

그 결과 현재의 온디바이스 LLM은 상태 없는 채팅봇으로 기능합니다. 사용자의 맥락을 "컨텍스트 윈도우에 때려 넣는 것" 외에 방법이 없고, 컨텍스트 윈도우의 크기는 유한하며, 매 질의마다 처음부터 다시 채워야 합니다. 수년치 개인 데이터는 바로 옆에 저장되어 있지만, 모델은 그것을 쿼리할 수 없습니다. 이는 아키텍처의 실패이지 모델의 실패가 아닙니다.

5. 올바른 해법이 갖춰야 할 조건

문제를 명확히 했으니, 올바른 해법이 가져야 할 구조적 조건들을 먼저 나열해보겠습니다. 이것은 어떤 특정 시스템을 추천하기 위한 준비가 아니라, 이 문제 공간에서 진지한 해법을 평가하는 기준을 세우기 위함입니다.

조건 1: 대수적 통합, 볼트온이 아님. 관계형, 전문 검색, 벡터, 그래프, 공간 질의가 같은 수학적 구조 위에서 표현 가능해야 합니다. 각 패러다임이 별도의 엔진이 아니라 같은 옵티마이저 아래의 연산자여야 합니다. 그래야 전역 최적화가 가능합니다.

조건 2: 원리적 점수 결합. 서로 다른 신호의 점수가 보정된 확률로 표현 가능해야 합니다. 임의의 가중 합산이 아니라 수학적으로 정당한 결합 규칙 — 예컨대 로그 오즈 공간에서의 결합, 혹은 베이지안 사후 분포의 결합 — 이 지원되어야 합니다. 이것 없이는 하이브리드 랭킹은 영원히 튜닝 숙제로 남습니다.

조건 3: 서버에서 임베디드까지 같은 엔진. 데이터센터와 온디바이스가 서로 다른 아키텍처의 엔진을 쓰면, 개발자는 두 세계를 모두 배워야 하고, 질의 의미론이 갈라집니다. SQLite가 "임베디드 관계형 DB"의 사실상 표준이 된 것은 같은 엔진이 모든 환경에서 동작하기 때문입니다. AI 시대의 데이터 레이어도 같은 성질이 필요합니다.

조건 4: 이론적 근거. 이 정도의 통합은 "있으면 좋은 기능"을 누적해서는 이룰 수 없습니다. 무엇이 통합되는지에 대한 수학적 정의가 선행되어야 합니다. 포스팅 리스트가 보편 추상화(universal abstraction)가 될 수 있는가? 관계 대수와 불리언 대수와 벡터 공간이 하나의 구조로 표현될 수 있는가? 이런 질문들이 먼저 답해져야 엔진의 구현이 일관된 모양을 가질 수 있습니다.

조건 5: 프로덕션 수준의 구현. 이론만으로는 아무도 쓰지 않습니다. 실제 워크로드를 처리할 수 있는 성능, 트랜잭션 보장, 기존 도구와의 호환성(PostgreSQL 와이어 프로토콜 등), 운영 경험이 필요합니다.

조건 6: 신뢰 가능한 공개성. 데이터 레이어는 애플리케이션이 의존하는 가장 깊은 의존성 중 하나입니다. 이 층위의 코드가 공개되어 있고, 이론이 발표되어 있고, 외부 검증이 있어야 합니다. 폐쇄적 상업 DB는 이 층위의 근본적 문제를 풀기에 부적절합니다 — 커뮤니티가 코드를 읽고 의심하고 기여할 수 없다면, 이 정도 규모의 통합은 신뢰받을 수 없습니다.

이 여섯 조건을 모두 만족시키는 시스템이 현재 시장에 존재할까요? 우리가 아는 한 없습니다. 각 조건을 부분적으로 만족시키는 시스템들은 있지만, 여섯 개를 모두 가진 것은 없습니다.

6. 하나의 구체적 응답: UQA와 Cognica 엔진

이 공백에 대한 하나의 구체적 응답이 Unified Query Algebra(UQA)와 그 프로덕션(production) 구현인 Cognica 엔진입니다. 두 이름은 의도적으로 분리되어 있습니다. UQA는 Python, TypeScript, C++ 세 구현에 걸쳐 의미 동등성(semantic equivalence)을 유지하는 수학적 사양이고, Cognica 엔진은 그 사양의 C++23 프로덕션 구현입니다. 이것을 "유일한 답"으로 제시하는 것이 아니라, 위에 열거한 여섯 조건에 대해 정확히 어떻게 대응하는지를 보이는 데이터 포인트로 제시합니다.

조건 1에 대한 대응 — 대수적 통합. UQA는 포스팅 리스트(정렬된 (id, payload) 쌍의 시퀀스)를 보편 추상화(universal abstraction)로 삼습니다. 관계형 필터, BM25 스코어링, 벡터 검색, 그래프 순회, 공간 질의 — 이 모두가 포스팅 리스트 위의 연산자로 컴파일됩니다.

이 통합이 실제로 무엇을 바꾸는지는 같은 질의를 두 가지 방식으로 나란히 써보는 것이 가장 직접적입니다. 다음 질의를 생각해보겠습니다: "2020년 이후의 논문 중에서, 제목에 '어텐션'과 관련된 내용이 있고, 주어진 임베딩 벡터와 의미적으로 가까우며, 특정 논문으로부터 인용 관계로 2-hop 이내에 연결된 것들을 점수 순으로." 현재의 분산된 스택으로 이 질의를 구현하면 대략 이런 모양이 됩니다.

# 1. 벡터 DB에서 후보 추출 (year 필터는 미리 적용) vec = pinecone.query( vector=query_emb, top_k=200, # 하위 단계 필터를 감안한 over-fetch filter={"year": {"$gte": 2020}}, ) cand_ids = [r.id for r in vec.matches] vec_score = {r.id: r.score for r in vec.matches} # 2. Elasticsearch에서 같은 후보에 대해 BM25 점수 es = elasticsearch.search( index="papers", body={ "query": { "bool": { "must": [{"match": {"title": "attention"}}], "filter": [{"terms": {"_id": cand_ids}}], } }, "size": 200, }, ) text_score = {h["_id"]: h["_score"] for h in es["hits"]["hits"]} # 3. Neo4j에서 논문 1로부터 2-hop 내 도달 가능성 g = neo4j.run( """ MATCH (src:Paper {id: $s})-[:CITED_BY*1..2]->(p:Paper) WHERE p.id IN $ids RETURN DISTINCT p.id AS id """, s=1, ids=cand_ids, ) graph_hit = {r["id"] for r in g} # 4. PostgreSQL에서 표시용 메타데이터 rows = pg.query( "SELECT id, title FROM papers WHERE id = ANY(%s)", (cand_ids,), ) title = {r.id: r.title for r in rows} # 5. 애플리케이션 메모리에서 점수 결합 # - 벡터: 코사인 유사도 ~ [0, 1] # - 텍스트: BM25, 범위 없음. 관측 최대값으로 정규화 # - 그래프: 이진 지시 함수 # 가중치는 오프라인 A/B로 수작업 튜닝 MAX_BM25 = 25.0 out = [] for id in cand_ids: if id not in title: continue s = ( 0.40 * vec_score.get(id, 0.0) + 0.40 * (text_score.get(id, 0.0) / MAX_BM25) + 0.20 * (1.0 if id in graph_hit else 0.0) ) out.append((title[id], s)) out.sort(key=lambda x: -x[1])

다섯 개의 시스템(벡터 DB, 전문 검색 엔진, 그래프 DB, 관계형 DB, 애플리케이션 런타임), 네 번의 네트워크 왕복, 그리고 수학적 근거 없이 선택된 세 개의 가중치입니다. 몇 가지 숨겨진 임의 결정들이 이 코드에 박혀 있습니다. cand_ids가 왜 벡터 DB에서 나와야 할까요? 다른 두 시스템이 대신 "1차 후보 생성기"가 될 수도 있었고, 그 결정에 따라 나머지 시스템에서 놓치는 후보의 집합이 완전히 달라집니다. 벡터 검색의 top_k=200은 어떻게 정해졌을까요 — 너무 작으면 실제로 관련 있는 논문이 다운스트림 필터에 도달하지 못하고, 너무 크면 지연이 누적됩니다. MAX_BM25 = 25.0은 관측으로 튜닝한 상수이며, 데이터 분포가 바뀌면 다시 튜닝해야 합니다. 그리고 이 모든 코드가 어느 엔진의 옵티마이저 바깥에 있기 때문에, 누구도 이 질의를 전체로서 최적화할 수 없습니다. 코드 작성자만이 그 책임을 집니다.

같은 의미의 질의가 UQA에서는 다음과 같이 표현됩니다.

SELECT title, _score FROM papers WHERE fuse_log_odds( text_match(title, 'attention'), bayesian_knn_match(embedding, $1, 10), traverse_match(1, 'cited_by', 2) ) AND year >= 2020 ORDER BY _score DESC;

텍스트 매칭, 벡터 유사도, 그래프 도달성, 관계형 필터가 하나의 옵티마이저 아래에서 비용 기반으로 재정렬되고, 하나의 실행 엔진에서 하나의 트랜잭션으로 처리됩니다. fuse_log_odds의 결합 규칙은 Bayesian BM25의 확률 보정 위에서 수학적으로 정당한 결합 분포이지, 임의 가중치의 합산이 아닙니다. top_kMAX_BM25 같은 임의 상수는 존재하지 않습니다. 후보 생성기 순서의 결정도 없습니다 — 그것은 옵티마이저의 일입니다. 앞 절에서 나열한 네 가지 문제 — 지연 누적, 비원리적 점수 결합, 저장 중복, 전역 최적화 불가 — 가 이 대조 하나에 모두 응답됩니다. 차이는 수사가 아니라 구조입니다.

조건 2에 대한 대응 — 원리적 점수 결합. Cognica 팀은 이 문제를 수년에 걸쳐 풀었습니다. Bayesian BM25는 BM25 점수를 시그모이드 변환을 통해 보정된 확률 [0, 1]로 변환합니다. 벡터 점수 보정은 ANN 인덱스의 통계로부터 우도비를 도출해 벡터 유사도를 적합성 확률로 변환합니다. 그리고 로그 오즈 공간에서의 결합 규칙이 수학적으로 정당한 결합 분포를 제공합니다. 이 작업의 일부인 Bayesian BM25는 Apache Lucene 코어에 병합되었고, MTEB 벤치마크의 공식 베이스라인으로 채택되었으며, Vespa.ai와 txtai 같은 정보 검색 프레임워크에 도입되었습니다. 이것은 학술적 주장이 아니라 산업에서 검증된 결과입니다.

조건 3에 대한 대응 — 서버에서 임베디드까지 같은 엔진. Cognica의 C++ 엔진은 모듈화되어 있어서 JIT 컴파일러, 바이트코드 VM 같은 서버용 구성 요소를 제거하고 임베디드 모드로 빌드할 수 있습니다. 같은 UQA 의미론, 다른 폼 팩터입니다. 그리고 병렬로 Python 레퍼런스 구현(cognica-io/uqa)과 TypeScript 브라우저 구현(cognica-io/uqa-js)이 존재합니다. 후자는 SQLite를 키-값 스토리지로 사용하며 HNSW 대신 온디스크(on-disk) IVF를 사용해 브라우저와 모바일 환경에 최적화되어 있습니다. 같은 UQA 사양이 C++, Python, TypeScript 세 구현에 걸쳐 의미 동등성(semantic equivalence)을 유지한다는 것은 UQA가 구현에 독립적인 사양임을 경험적으로 보여줍니다.

조건 4에 대한 대응 — 이론적 근거. UQA는 다섯 편의 이론 논문 위에 세워져 있습니다.

  1. 관계형, 텍스트, 벡터, 그래프 패러다임을 위한 통합 수학적 프레임워크. 포스팅 리스트를 보편 추상화로 삼아 불리언 대수 위에서 각 패러다임을 표현합니다.
  2. 포스팅 리스트-그래프 동형성을 통한 그래프 대수의 통합. 그래프 순회와 패턴 매칭이 포스팅 리스트 연산으로 매핑됩니다.
  3. Bayesian BM25의 확률적 프레임워크. BM25 점수를 보정된 확률로 변환하는 수학적 필연성을 유도합니다.
  4. 베이지안 추론에서 신경 계산으로. 신경망의 구조가 다중 신호 베이지안 추론에서 해석적으로 도출(emerge)된다는 결과입니다. 활성화 함수가 확률적 질문의 답으로 유도됩니다.
  5. 벡터 점수의 우도비 보정. ANN 인덱스의 분포 통계를 활용해 벡터 유사도를 적합성 확률로 변환하는 인덱스-인식 방법입니다.

이 구조의 기초(foundation)는 집합론만으로 완전히 세워집니다. 포스팅 리스트가 문서 멱집합(document power set)과 전단사(bijection)를 이룬다는 정의 하나로부터 불리언 대수의 모든 성질이 따라 나오고, 그 대수 위에서 각 패러다임이 자연스럽게 자리를 찾습니다. 이 최소성 자체가 구조의 근본성을 보이는 가장 강한 증거입니다. 복잡한 기초가 필요 없다는 것은, 통합이 만들어낸 것이 아니라 이미 거기 있던 구조를 본 것에 가깝다는 뜻입니다.

첫 번째 논문의 7절에는 격자 이론(lattice theory)을 사용한 추가 관점이 등장합니다. 질의 공간을 부분 순서(partial order) 위의 완비 격자(complete lattice)로 재해석하는 것인데, 이것의 기원은 이론적 일반화가 아니라 실용적 고민이었습니다. 질의 최적화를 진지하게 추구하기 시작하면 질의들 사이의 관계가 어떤 구조를 가지는지를 묻게 되고, 그 질문에 대한 자연스러운 답이 완비 격자입니다. 중요한 것은 이것이 새로운 발견이 아니라 포스팅 리스트의 불리언 대수가 이미 그 격자 구조를 내포하고 있었다는 인식이라는 점입니다. 실용적 문제가 이미 존재하던 구조의 한 측면을 드러냈습니다.

이런 종류의 일 — 새로운 문제 영역이 기존 구조의 한 얼굴이었음이 뒤늦게 드러나는 일 — 이 UQA 프레임워크 전반에서 반복적으로 일어납니다. 그래프, 확률 보정, 신경 계산, 벡터 보정으로의 확장은 모두 같은 패턴을 따릅니다. 각 확장은 새 구조를 만든 것이 아니라 이미 있는 구조가 해당 영역을 어떻게 표현하는지를 보이는 작업이었습니다. 다섯 편의 논문을 관통하는 일관성은 의도된 설계라기보다 이 패턴의 반복입니다.

가장 최근의 예는 공간 질의의 통합입니다. R-Tree 공간 인덱스, 공간 술어(within, intersects, contains), 거리 함수가 포스팅 리스트 대수 위의 추가 연산자로 편입되었습니다. 이것 역시 프레임워크에 새로운 공리를 더한 것이 아니라 같은 구조가 공간 정보를 어떻게 다룰 수 있는지를 보이는 작업이었습니다. 공간 술어는 포스팅 리스트의 부분집합을 선택하는 필터이고, 거리 함수는 점수이고, 공간 인덱스는 그 필터를 효율적으로 평가하기 위한 접근 경로일 뿐입니다. 패턴이 지금도 계속되고 있다는 가장 직접적인 증거이며, 동시에 이 프레임워크가 미래에 등장할 다른 종류의 데이터 — 센서 스트림, 시계열, 텐서 필드 — 도 같은 방식으로 흡수할 여지가 있다는 신호입니다.

이것이 중요한 이유는 단지 수학적 우아함의 문제가 아닙니다. 통합이 최소 기초 위에서 성립하고, 서로 다른 영역으로의 확장이 반복적으로 같은 패턴을 따른다는 것은, 앞으로 등장할 새로운 패러다임 — 지금 우리가 이름조차 모르는 — 도 같은 프레임워크 안에 자연스럽게 자리잡을 가능성이 높다는 것을 의미합니다. 집합론이 현대 수학 전체의 기초로 기능할 수 있는 것과 같은 이유로, 집합 위의 불리언 대수는 계산 가능한 데이터 구조의 거의 모든 종류를 포섭할 여지를 가집니다.

조건 5에 대한 대응 — 프로덕션 수준의 구현. Cognica 엔진은 80만 라인 이상의 C++23 코드이며, PostgreSQL 17과 거의 완전히 호환되는 SQL(103개 기능 중 95개), ACID 트랜잭션, DPccp 조인 순서 결정 알고리즘, Copy-and-Patch JIT 컴파일, Raft 합의 프로토콜, MVCC 기반 격리 수준, Cypher 그래프 질의(Apache AGE 호환), R-Tree 공간 인덱스와 공간 술어, Apache Arrow 컬럼형 실행, 그리고 DuckDB와 Arrow Flight SQL을 통한 외부 데이터 연동을 지원합니다. 이것은 연구 프로토타입이 아니라 실제 워크로드를 다루는 엔진입니다. 서버 모드(PostgreSQL 와이어 프로토콜)와 임베디드 모드(SQLite/DuckDB 스타일 라이브러리 임베딩) 모두를 지원합니다.

조건 6에 대한 대응 — 신뢰 가능한 공개성. UQA 레퍼런스 구현은 AGPL-3.0으로 공개되어 있습니다. 이론 논문 다섯 편이 모두 공개되어 있습니다. 그리고 Cognica 엔진의 내부 아키텍처를 설명하는 34개 챕터로 구성된 교과서 Cognica Database Internals가 무료로 공개되어 있습니다 — LSM-tree 저장 구조, CVM 바이트코드 인터프리터, Copy-and-Patch JIT, Zero-Copy JOIN, WAND/BMW 평가 전략, Raft 합의, Cypher-over-SQL 재작성, 벡터 점수 보정까지 모든 층이 문서화되어 있습니다. 이는 상업용 데이터베이스 회사에서 거의 찾아볼 수 없는 수준의 공개성이며, 독자가 주장을 확인하기 위해 이론, 구현, 설명을 모두 대조해볼 수 있다는 의미입니다.

7. 남은 질문과 한계

위의 여섯 조건에 대한 대응을 열거했지만, Cognica가 문제를 해결했다고 주장하고 싶지는 않습니다. 몇 가지 솔직한 한계를 명시해야 합니다.

스케일 검증. Cognica 엔진은 기술적으로 100TB 단일 노드를 다룰 수 있도록 설계되었지만, 수십 개 노드에 걸친 페타바이트급 분산 워크로드에서의 검증은 아직 진행 중입니다. 데이터센터 쪽의 가장 큰 고객이 요구하는 규모에서의 입증은 앞으로의 과제입니다.

온디바이스 배포의 성숙도. 임베디드 모드는 아키텍처적으로 가능하지만, iOS/Android에 실제로 배포되어 배터리, 메모리, 콜드 스타트 지연이 프로덕션 수준에 도달했는가는 별개의 질문입니다. 이 영역은 현재 적극적으로 개발 중입니다.

생태계. SQLite가 이토록 편재하게 된 것은 기술 때문만이 아니라, 수십 년에 걸친 도구 생태계(드라이버, ORM, 관리 도구, 교재) 때문이기도 합니다. UQA는 PostgreSQL 와이어 프로토콜 호환성으로 기존 도구 생태계의 상당 부분을 활용할 수 있지만, "AI 네이티브 데이터 레이어"에 특화된 도구들 — 예컨대 하이브리드 질의 디버거, 신호 보정 분석 도구, 임베디드용 인덱스 시각화 — 은 아직 만들어지지 않았습니다.

검증 가능한 외부 채택. Bayesian BM25가 Lucene 코어에 병합되고 Vespa에 채택된 것은 신호이지만, Cognica 엔진 전체가 외부 프로덕션 시스템에서 검증되는 단계까지는 아직 가지 않았습니다. 이는 초기 채택자들과의 협업이 필요한 단계입니다.

이 한계들은 Cognica의 구조적 접근이 틀렸음을 의미하지 않습니다. 오히려 이 한계들이 해결될 수 있는 종류의 문제라는 것, 그리고 기초가 올바르게 놓여 있다면 이 한계들을 극복하는 것이 가능하다는 것을 의미합니다. 구조적 문제가 잘못 풀린 시스템은 아무리 엔지니어링을 해도 극복할 수 없습니다. 구조적 문제가 올바르게 풀린 시스템은 시간이 지나면서 성숙해집니다.

결론: 답이 아니라 시작

이 글의 목적은 "Cognica를 써라"를 설득하는 것이 아닙니다. 목적은 두 가지였습니다.

첫째, 현재 AI 인프라 스택에 보이지 않는 층위의 공백이 있음을 분명히 하는 것입니다. 모델과 하드웨어 사이에 있어야 할 데이터 레이어가 파편화되어 있고, 온디바이스에서는 거의 존재하지 않습니다. 이것은 "조금 불편한 현 상태"가 아니라 구조적 문제이며, 현재의 RAG 프레임워크나 벡터 DB 확장으로는 해결되지 않습니다.

둘째, 이 문제에 대한 올바른 해법이 가져야 할 조건을 명시하는 것입니다. 대수적 통합, 원리적 점수 결합, 서버-임베디드 통합, 이론적 근거, 프로덕션 수준, 공개성. 이 여섯 조건은 평가 기준입니다. 어떤 시스템을 고려하든, 이 여섯 조건을 얼마나 만족하는지를 물어봐야 합니다.

Cognica 엔진은 이 조건들에 대한 하나의 응답입니다. 아마 유일한 응답은 아닐 것입니다. 이 문제가 구조적임이 넓게 인지되면, 다른 팀들도 자기 방식으로 답을 만들어낼 것이고, 그 과정에서 이 공간의 올바른 모양이 드러날 것입니다. 우리는 그런 방향으로 대화가 움직이기를 기대합니다.

당장 할 수 있는 일이 있다면, 자신이 지금 구축하고 있는 AI 시스템이 위의 여섯 조건을 얼마나 만족하는지 평가해보는 것입니다. 대부분의 경우 답은 "많이 부족하다"일 것이고, 그 부족함이 우연한 것인지 구조적인 것인지를 구별하는 것이 다음 단계입니다. 구조적 부족함은 글루 코드로 해결되지 않습니다.

참고 자료

Copyright (c) 2023-2026 Cognica, Inc.