LLM WikiAccess-protected knowledge portal
← 스터디 홈
46편 · 약 15분

SurrealDB 3.0~3.2: 문서·그래프·벡터를 하나의 ACID 쿼리로 묶는 AI 에이전트 메모리 레이어

왜 지금 봐야 하나

LLM 기반 에이전트를 프로덕션에 올릴 때 흔히 마주치는 것이 "5개 데이터베이스 문제"다. 에이전트에게는 관계형 데이터(사용자 프로필, 이력), 문서(대화 내용, 지식 청크), 벡터 임베딩(의미 검색), 그래프(엔티티 간 관계), 캐시(세션 상태)가 모두 필요하다. 이것들을 PostgreSQL, MongoDB, Chroma, Neo4j, Redis로 분산시키면 쿼리 하나가 다섯 번의 네트워크 왕복이 되고, 다섯 개 클라이언트를 관리해야 하며, 트랜잭션 경계가 시스템 외부에서 제어된다.

SurrealDB 3.0은 이 문제를 "하나의 엔진 안에서 다섯 가지 모델을 ACID로 묶는다"는 방향으로 접근한다. 2026년 2월 17일 $23M 시리즈 A와 함께 출시됐고, SurrealDB 3.2.0(2026년 7월 6일), 3.2.1(2026년 7월 10일)이 현재 안정 버전이다.

이 글은 SurrealDB 3.x가 기존 2.x 대비 어떤 아키텍처 변화를 가져왔는지, SurrealQL 하나로 관계·그래프·벡터를 함께 쿼리하는 방식, 그리고 2.x에서 마이그레이션할 때 반드시 알아야 할 경계를 다룬다.


SurrealDB의 멀티모델 아키텍처

SurrealDB 3.x: 단일 엔진 멀티모델 아키텍처 기존: 5개 데이터베이스 스택 PostgreSQL 사용자 프로필, 이력, 관계형 조인 MongoDB 대화 내용, 지식 청크 (문서) Chroma / Qdrant 임베딩 벡터, 의미 유사도 검색 Neo4j 엔티티 관계, 지식 그래프 Redis 세션 캐시, 단기 메모리 문제점 • 5개 클라이언트 관리 • 교차 모델 트랜잭션 없음 SurrealDB SurrealDB 3.x: 단일 엔진 SurrealQL 쿼리 레이어 관계형·문서·벡터·그래프·집계를 하나의 SQL 방언으로 관계형 DEFINE TABLE DEFINE FIELD JOIN 지원 엄격한 스키마 가능 문서 중첩 오브젝트 동적 필드 배열 지원 스키마 선택적 벡터 HNSW / MTREE kNN 검색 array<float> 타입 코사인·유클리드·맨해튼 그래프 record link ->/<- 순방향/역방향 다홉 traversal 가중치 엣지 가능 에이전트 메모리 Context Graph 장기/단기 메모리 세션 연속성 에이전트 체인 가능 ACID 트랜잭션 레이어 (클라이언트 사이드 + 서버 사이드) BEGIN … COMMIT 으로 여러 모델에 걸친 원자적 쓰기 보장 SurrealDB 3.0 핵심 아키텍처 변화 • 온디스크 문서 표현 재설계 • 값(value)과 표현식 분리 • Computed Fields (COMPUTED 키워드) • ID 기반 메타데이터 저장소 스토리지 백엔드 임베디드: RocksDB (단일 노드) | 분산: TiKV (클러스터)
SurrealDB 3.x 멀티모델 아키텍처: 하나의 SurrealQL로 5가지 모델 접근

SurrealDB 3.0의 아키텍처 변화

SurrealDB 3.0이 2.x 대비 가장 크게 바꾼 것은 세 가지다.

1. 온디스크 문서 표현 재설계

2.x에서 레코드는 값과 표현식을 혼합해 디스크에 저장했다. 예를 들어 future 타입(<future>{ time::now() })은 레코드 안에 저장되어 읽기 시점마다 재평가됐다. 3.0은 저장되는 값실행 시점에 평가되는 표현식을 완전히 분리한다. 디스크에는 순수 데이터만 저장되고, 파생 필드는 스키마에 선언된 표현식으로 계산된다.

이 변화의 결과로 레코드 당 런타임 평가 오버헤드가 줄었고, 인덱스 일관성이 높아졌다.

2. Computed Fields (COMPUTED 키워드)

<future> 타입이 완전히 제거되고 COMPUTED 필드로 대체됐다. 2.x에서는 레코드를 생성할 때 VALUE <future> { expression } 형태로 지연 계산을 정의했다.

-- 2.x: future 타입으로 파생 필드 정의 (3.0에서 제거됨)
DEFINE FIELD full_name ON person VALUE <future> {
  string::concat(first_name, " ", last_name)
};

-- 3.0: COMPUTED 키워드로 대체
DEFINE FIELD full_name ON person
  TYPE string
  COMPUTED string::concat(first_name, " ", last_name);

COMPUTED 필드의 특징은 다음과 같다.

  • 스키마에 한 번 선언되면 모든 읽기 시점에 일관되게 평가된다.
  • 레코드 당 표현식을 저장하지 않으므로 디스크 사용량이 줄어든다.
  • 조건이 필요하면 인라인 조건식을 사용한다 (IF THEN ELSE END).

마이그레이션 주의: DEFAULT <future> 또는 CREATE ... SET field = <future> 형태로 레코드에 직접 저장된 future는 3.0에서 직접 대응하는 개념이 없다. 스키마를 재설계해야 한다.

3. ID 기반 메타데이터 저장소와 동기 쓰기 기본화

테이블 정의, 인덱스 정의, 접근 제어 등 메타데이터가 이전보다 예측 가능한 ID 기반 스토리지로 이동했다. 이에 맞춰 동기 쓰기(synced writes)가 기본값이 됐다. 2.x에서는 비동기 쓰기가 기본이었고 일부 시나리오에서 메타데이터와 데이터 간 일관성 문제가 생길 수 있었다. 3.0부터 쓰기가 완전히 커밋되기 전까지 응답을 반환하지 않는다.

이 변화는 쓰기 지연을 소폭 높이는 대신, 충돌 후 복구 시나리오에서 안전성을 높인다.


SurrealQL: 한 쿼리로 관계·그래프·벡터 결합

SurrealQL의 가장 큰 특징은 세 가지 쿼리 패턴을 하나의 문장에서 결합할 수 있다는 점이다.

그래프 순회

-> (순방향)와 <- (역방향) 연산자로 레코드 간 관계를 탐색한다. 관계 테이블(엣지 테이블)이 그래프의 간선 역할을 한다.

-- 사용자 A가 "구매한" 상품 중 카테고리가 "도서"인 것
SELECT ->purchased->product[?category == "book"] AS books
FROM user:alice;

-- 2홉: 친구의 친구가 작성한 리뷰
SELECT ->knows->user->wrote->review.* AS friend_reviews
FROM user:alice;

벡터 kNN 검색

HNSW 인덱스가 정의된 필드에 <|k,ef|> 연산자로 kNN 검색을 수행한다.

-- 임베딩으로 유사 문서 5개 조회
SELECT id, title, vector::distance::knn() AS score
FROM document
WHERE embedding <|5,100|> $query_embedding
ORDER BY score;

<|5,100|>에서 5는 k(결과 수), 100은 ef_search(탐색 범위, 높을수록 정확도 증가·속도 감소)다.

관계·그래프·벡터 복합 쿼리

-- 에이전트 메모리 검색: 현재 대화와 의미적으로 유사하고
-- 이전 세션에서 접근한 적 있는 문서를 그래프로 연결
SELECT
    m.content,
    m.created_at,
    vector::distance::knn() AS relevance,
    count(m<-accessed<-session) AS access_count
FROM memory:agent_alice AS m
WHERE
    m.embedding <|10,200|> $current_embedding
    AND access_count > 0
ORDER BY relevance, access_count DESC
LIMIT 5;

이 쿼리는 단일 왕복으로 세 가지를 결합한다:

  1. 벡터 인덱스로 의미적 유사도 상위 10개 후보 필터
  2. 그래프 역방향 탐색으로 이전 세션에서 접근된 메모리만 남김
  3. 접근 횟수로 2차 정렬

에이전트 메모리를 위한 Context Graph 설계

SurrealDB 3.0이 가장 강조하는 사용 사례는 AI 에이전트의 영속 메모리다. 기본 아이디어는 다음과 같다.

단기 메모리는 현재 세션의 대화 내용이다. 세션이 끝나면 임시 플래그가 붙는다.

장기 메모리는 여러 세션에 걸쳐 중요하다고 판단된 정보다. 임베딩을 함께 저장해 의미 검색으로 회수한다.

관계 그래프는 메모리 노드 간 의미 연결이다. "X를 좋아한다", "Y에 관심 있다", "Z 주제에서 전문가다" 같은 관계를 엣지로 표현한다.

-- 에이전트 메모리 테이블 정의
DEFINE TABLE memory SCHEMAFULL;
DEFINE FIELD agent    ON memory TYPE record<agent>;
DEFINE FIELD content  ON memory TYPE string;
DEFINE FIELD embedding ON memory TYPE array<float>;
DEFINE FIELD tier     ON memory TYPE string   -- "short_term" | "long_term"
  DEFAULT "short_term";
DEFINE FIELD created_at ON memory TYPE datetime
  DEFAULT time::now();

-- 벡터 인덱스 (HNSW, 코사인 유사도)
DEFINE INDEX memory_vec ON memory
  FIELDS embedding HNSW DIMENSION 1536 DIST COSINE;

-- 관계 엣지 테이블
DEFINE TABLE connects SCHEMAFULL;
DEFINE FIELD in     ON connects TYPE record<memory>;
DEFINE FIELD out    ON connects TYPE record<memory>;
DEFINE FIELD reason ON connects TYPE string;
DEFINE FIELD weight ON connects TYPE float DEFAULT 1.0;

-- 장기 메모리 승격 쿼리
UPDATE memory SET tier = "long_term"
WHERE agent = $agent_id
  AND importance_score > 0.8
  AND tier = "short_term";

에이전트가 새로운 정보를 처리할 때:

  1. 현재 컨텍스트 임베딩으로 관련 장기 메모리를 kNN 조회
  2. 새 정보를 단기 메모리로 저장
  3. 관련 장기 메모리와 connects 엣지 생성
  4. 주기적으로 중요도 점수 기반 장기 메모리 승격

전체 흐름이 단일 SurrealDB 트랜잭션으로 묶이므로 쓰기 도중 실패해도 메모리 상태가 일관성을 유지한다.


2.x에서 3.x로 마이그레이션할 때 반드시 확인할 사항

제거된 기능

2.x 기능3.x 대응참고
<future>{ expr } 타입COMPUTED expr 필드스키마에 선언, 레코드 재설계 필요
type::is::*() 함수군타입 캐스트 <T>valuetype::is::string(v)<string>v 사용
비동기 쓰기 기본값동기 쓰기 기본값지연 변화 확인 필요

온디스크 포맷 변화

SurrealDB 3.0은 내부 문서 표현 포맷이 달라졌다. 2.x 데이터를 3.x로 이전할 때는 공식 마이그레이션 가이드(/docs/build/migrating/from-old-surrealdb-versions/2x-to-3x)에 따라 내보내기·재가져오기 절차를 따라야 한다. 직접 스토리지 파일 복사로는 동작하지 않는다.

클라이언트 사이드 트랜잭션

3.0에서 추가된 클라이언트 사이드 트랜잭션은 여러 요청에 걸쳐 트랜잭션 상태를 클라이언트가 관리한다.

// Node.js / Python SDK 클라이언트 사이드 트랜잭션
const txn = await db.beginTransaction();
try {
    await txn.query("INSERT INTO memory { agent: $agent, content: $content }", params);
    await txn.query("RELATE $mem->connects->$related SET reason = $reason", linkParams);
    await txn.commit();
} catch (e) {
    await txn.rollback();
    throw e;
}

주의할 점은 이 트랜잭션이 서버 상태를 소유한다는 것이다. 클라이언트가 커밋 전에 연결을 잃으면 서버 측에서 타임아웃 후 롤백된다. 다중 레플리카 환경에서는 항상 같은 노드로 연결하거나 로드밸런서에 세션 어피니티를 설정해야 한다.


SurrealDB 3.2.x 변화 요약 (2026-07-06 / 07-10)

3.0에서 3.2까지의 변화는 주로 안정성과 성능이다.

  • HNSW 인덱스 빌드 성능: 대용량 데이터셋에서 인덱스 빌드 시간 단축.
  • 동시 쓰기 안정성: 높은 동시성 쓰기에서 발생하던 교착 가능성 수정.
  • SurrealQL 파서 개선: 복합 그래프 표현식에서 파싱 오류 수정.
  • 임베디드 모드 개선: surrealdb::engine::local::Db 사용 시 메모리 누수 패치.

현재 안정 추천 버전은 3.2.1(2026-07-10)이다.


운영 고려사항

단일 노드 vs 분산

SurrealDB는 두 가지 스토리지 백엔드를 제공한다.

  • RocksDB (임베디드): 단일 프로세스, 로컬 파일. 소규모 또는 개발 환경에 적합. 수평 확장 불가.
  • TiKV (분산): Raft 기반 분산 KV 스토어. 수평 확장 가능. 별도 TiKV 클러스터 운영 필요.

벡터 인덱스와 그래프 순회는 TiKV 모드에서도 동작하지만, kNN 쿼리의 경우 데이터가 여러 노드에 분산되어 있으면 모든 노드에서 부분 결과를 모아 합산(merge ANN)하는 방식이다. 이 과정에서 네트워크 오버헤드가 추가된다. 수십억 벡터 이상에서의 분산 kNN 성능은 전용 벡터 DB 대비 아직 검증 사례가 적다.

임베딩 생성은 외부에서

SurrealDB는 임베딩을 저장하고 검색하지만, 텍스트에서 임베딩을 생성하는 기능은 없다. 애플리케이션 계층에서 임베딩을 생성한 후 SurrealDB에 저장해야 한다.

# 에이전트 메모리 저장 예시 (Python)
from sentence_transformers import SentenceTransformer

model = SentenceTransformer("all-MiniLM-L6-v2")
embedding = model.encode(memory_content).tolist()

await db.query(
    "INSERT INTO memory { agent: $agent, content: $content, embedding: $vec }",
    { "agent": agent_id, "content": memory_content, "vec": embedding }
)

적합한 사용 사례

사용 사례SurrealDB 적합 여부이유
AI 에이전트 메모리 (수백만 레코드)적합멀티모델 + ACID + 단순 운영
수십억 벡터 전용 검색검토 필요Qdrant/Milvus 대비 kNN 대규모 검증 부족
기존 PostgreSQL 대체신중마이그레이션 비용, 생태계 성숙도 차이
프로토타입·소규모 RAG적합임베디드 RocksDB로 의존성 없이 시작

운영 체크리스트

  • [ ] SurrealDB 3.2.1 버전을 사용하는가? (3.0.0 → 3.2.1까지 여러 안정성 패치 포함)
  • [ ] 2.x에서 마이그레이션 시 공식 2x-to-3x 가이드를 따랐는가?
  • [ ] <future> 타입이 코드베이스에 남아 있지 않은가?
  • [ ] HNSW 인덱스의 ef_search 값이 워크로드에 맞게 설정됐는가?
  • [ ] 클라이언트 사이드 트랜잭션 사용 시 세션 어피니티 또는 단일 노드 연결을 보장하는가?
  • [ ] 임베딩 생성 파이프라인이 SurrealDB 외부에서 관리되는가?
  • [ ] 분산 모드(TiKV) 사용 시 TiKV 클러스터 별도 운영 계획이 있는가?
  • [ ] 동기 쓰기 기본화에 따른 p99 쓰기 지연 변화를 측정했는가?

References

  • SurrealDB, "Introducing SurrealDB 3.0 — the future of AI agent memory", surrealdb.com/blog, 2026-02-17. https://surrealdb.com/blog/introducing-surrealdb-3-0--the-future-of-ai-agent-memory
  • SurrealDB, "SurrealDB 3.0 overview", surrealdb.com/3.0. https://surrealdb.com/3.0
  • SurrealDB Documentation, "2.x to 3.x migration guide". https://surrealdb.com/docs/build/migrating/from-old-surrealdb-versions/2x-to-3x
  • SurrealDB Documentation, "Vector Indexes: HNSW and MTREE". https://surrealdb.com/docs/learn/data-models/vector-search/vector-indexes
  • SurrealDB Documentation, "DEFINE INDEX statement". https://surrealdb.com/docs/surrealql/statements/define/indexes
  • SurrealDB, "Release 3.1 changelog". https://surrealdb.com/releases/3.1
  • SurrealDB, "Release Notes and Changelog". https://surrealdb.com/releases
  • VentureBeat, "SurrealDB 3.0 wants to replace your five-database RAG stack with one". https://venturebeat.com/data/surrealdb-3-0-wants-to-replace-your-five-database-rag-stack-with-one
  • Helge Sverre, "SurrealDB 3.0: What's Really New? (Beyond the Speed Hype)". https://helgesver.re/articles/surrealdb-3-whats-really-new
  • SiliconANGLE, "SurrealDB raises $23M to expand AI-native multimodel database", 2026-02-17. https://siliconangle.com/2026/02/17/surrealdb-raises-23m-expand-ai-native-multi-model-database/