Turso: SQLite를 Rust로 재작성한 프로젝트. 설정 가이드 및 도입 가치 분석
요약
Turso는 SQLite와 호환되면서 Rust로 재작성된 인프로세스 SQL 데이터베이스 프로젝트입니다. MVCC를 통한 동시 쓰기 지원, 비동기 I/O 설계, 내장된 벡터 검색 등 기존 SQLite의 한계를 극복한 다양한 기능을 제공합니다.
핵심 포인트
- Rust 기반의 비동기 I/O 및 MVCC 지원으로 동시 쓰기 성능 개선
- RAG 워크로드를 위한 네이티브 벡터 검색 기능 내장
- SQLite와 동일한 SQL 방언 및 파일 형식 유지로 높은 호환성 제공
- 실시간 변경 데이터 캡처(CDC) 및 전체 텍스트 검색 지원
최근 GitHub의 SQLite 관련 분야를 살펴본 적이 있다면, 아마 Turso라는 이름을 접해 보셨을 것입니다. Turso 프로젝트는 스스로를 SQLite와 호환되는 Rust로 작성된 인프로세스(in-process) SQL 데이터베이스라고 설명합니다.
이 포스트에서는 이 프로젝트가 실제로 무엇인지, 로컬 및 클라우드 환경에서 어떻게 실행하는지, 그리고 지금 당장 이를 도입할 가치가 있는지에 대한 솔직한 의견을 살펴봅.
먼저, 명칭의 혼란을 정리합시다
코드를 만지기 전에, 서로 관련이 있지만 서로 다른 세 가지 요소가 있다는 점을 아는 것이 도움이 됩니다. 이들을 혼동하는 것이 커뮤니티에서 발생하는 가장 흔한 혼란의 원인입니다:
-
libSQL: Turso의 원래 프로젝트로, C로 작성된 SQLite의 포크(fork) 버전입니다. 현재 프로덕션 환경에서 사용할 수 있는 수준이며, 현재 Turso Cloud를 구동하고 있습니다.
-
Turso (데이터베이스 엔진): 위 GitHub 링크에 있는 프로젝트입니다.
-
여전히 SQLite와 통신합니다. 동일한 SQL 방언 (SQL dialect), 동일한 파일 형식, 그리고 가능한 범위 내에서 동일한 C API 표면 (API surface)을 유지합니다. SQLite를 알고 있다면, 이미 Turso의 대부분을 알고 있는 것과 다름없습니다.
-
동시 쓰기 (Concurrent writes). SQLite에 대한 역사적인 가장 큰 불만은 단일 작성자 잠금 (single-writer lock) 방식입니다. Turso는
BEGIN CONCURRENT를 지원하는 실험적인 MVCC (Multi-Version Concurrency Control) 엔진을 제공하여, 단순한 사례의 경우 여러 작성자가 서로를 차단하지 않고 커밋할 수 있도록 합니다. -
설계 단계부터 비동기 (Async by design). 대부분의 SQLite 드라이버가 동기식 코어 위에 비동기 동작을 덧붙여야 하는 것과 달리, 이 엔진은 비동기 I/O (Linux io_uring 포함)를 중심으로 구축되었습니다.
-
네이티브 벡터 검색 (Native vector search). 임베딩 (embeddings) 및 RAG 스타일 워크로드를 위한 근사 벡터 검색 (approximate vector search) 기능이 확장 프로그램 없이 내장되어 있습니다.
-
변경 데이터 캡처 (Change Data Capture, CDC). 데이터베이스에 수행된 모든 변경 사항을 실시간으로 추적하며, 이는 Turso의 새로운 동기화 (sync) 기능의 중추 역할을 합니다.
-
전체 텍스트 검색 (Full-text search). tantivy 라이브러리를 통해 별도의 확장 프로그램 없이 지원됩니다.
-
저장 시 암호화 (Encryption at rest) 및 증분 뷰 유지 관리 (incremental view maintenance) (DBSP를 통해 제공). 두 기능 모두 현재 실험적 단계로 표시되어 있습니다.
-
즉시 사용 가능한 다국어 지원 (Multi-language support out of the box): Rust, JavaScript/TypeScript, Python, Go를 위한 공식 패키지를 제공하며, 생태계 내에서 더 많은 커뮤니티 드라이버(PHP/Laravel, .NET)가 등장하고 있습니다.
-
진정으로 개방된 기여 모델. 폐쇄적인 테스트 스위트를 사용하는 SQLite의 코어와 달리, Turso는 외부 기여자들이 자신의 변경 사항을 검증할 수 있도록 SQLite 자체의 바이트코드 (bytecode) 출력에 대해 공개적인 결정론적 시뮬레이션 테스트 (deterministic simulation testing) 및 퍼징 (fuzzing)을 사용하여 구축되었습니다.
요약하자면: 더 안전한 메모리 처리, 실제 동시 쓰기, 그리고 내장된 벡터 검색 기능을 갖춘 SQLite를 원했다면, 이 프로젝트는 바로 당신을 겨냥하고 있습니다.
로컬 환경 설정하기
1. CLI 설치
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/tursodatabase/turso/releases/latest/download/turso_cli-installer.sh | sh
Windows 사용자는 대신 릴리스 (releases) 페이지에 링크된 PowerShell 설치 프로그램을 사용할 수 있습니다.
2. 셸 실행
tursodb
이 명령을 실행하면 일시적인 인메모리 데이터베이스 (in-memory database)에 연결된 대화형 셸 (interactive shell)로 진입합니다.
turso> CREATE TABLE users (id INT, username TEXT);
turso> INSERT INTO users VALUES (1, 'alice');
turso> INSERT INTO users VALUES (2, 'bob');
...
인메모리 데이터베이스 대신 영구적인 파일을 사용하려면 셸 내부에서 .open FILENAME을 사용하세요.
3. Docker를 선호하시나요, 아니면 소스에서 직접 빌드하시나요?
# 개발 버전을 빌드하고 실행
cargo run
...
4. 언어 바인딩 (language binding) 선택
Rust:
cargo add turso
let db = Builder::new_local("sqlite.db").build().await?;
let conn = db.connect()?;
let res = conn.query("SELECT * FROM users", ()).await?;
JavaScript/TypeScript:
npm install @tursodatabase/database
import { connect } from '@tursodatabase/database';
const db = await connect('sqlite.db');
const stmt = db.prepare('SELECT * FROM users');
...
Python:
uv pip install pyturso
import turso
con = turso.connect("sqlite.db")
cur = con.cursor()
...
Go:
go get turso.tech/database/tursogo
conn, _ := sql.Open("turso", "sqlite.db")
defer conn.Close()
이것으로 로컬 설정이 모두 완료되었습니다. 서버도, 데몬 (daemon)도, 설정 파일도 필요하지 않습니다. 기존 SQLite가 항상 그래왔던 것처럼 프로세스 내부 (in-process)에서 실행됩니다.
클라우드 동기화 설정하기
원격 기본 데이터베이스 (remote primary)와 동기화 상태를 유지하는 로컬 우선 (local-first) 앱을 원한다면, Turso의 최신 동기화 패키지가 핵심적인 역할을 합니다.
npm install @tursodatabase/sync
import { connect } from "@tursodatabase/sync";
const db = await connect({
...
url 및 authToken 필드를 위해 Turso Cloud 데이터베이스와 인증 토큰 (auth token)이 필요하며, 두 가지 모두 turso CLI 또는 Turso 대시보드를 통해 사용할 수 있습니다. 이 동기화 계층은 libSQL의 이전 기능인 "임베디드 레플리카 (embedded replicas)"를 대체하는 것으로, 프로젝트 팀은 비동기 페이지 수준 동기화 프로토콜 (async, page-level sync protocol) 덕분에 더 빠른 레플리카 부트스트랩 (replica bootstrap)과 낮은 대역폭 사용이 가능하다는 점을 들어, 모든 새로운 동기화 작업에 대해 기존 방식 대신 이 방식을 권장하고 있습니다.
솔직한 주의사항
저장소 자체에서도 이 점을 솔직하게 밝히고 있으며, 대충 넘어가기보다는 다시 한번 강조할 가치가 있습니다. 이 소프트웨어는 베타(beta) 단계입니다. 유지 관리자들은 버그와 예상치 못한 동작이 발생할 수 있다고 명시적으로 경고하며, 프로덕션(production) 데이터 사용 시 주의를 기울이고 적절한 백업을 수행할 것을 권장합니다.
도입을 결정하기 전에 알아두어야 할 몇 가지 구체적인 사항은 다음과 같습니다:
- 현재 MVCC에는 실질적인 한계가 있습니다. 현재 MVCC가 활성화된 데이터베이스에는 인덱스(Index)를 생성할 수 없으며, 첫 접근 시 전체 데이터셋이 메모리에 즉시 로드(eagerly loaded)되므로 매우 큰 데이터베이스의 경우 시작 속도가 느리고 메모리 소모가 클 수 있습니다.
- 쿼리 결과의 정렬(ordering)이 모든 경우에 SQLite와 일치한다고 보장할 수 없습니다. 이는 테스트나 애플리케이션 로직이 암묵적으로 행(row) 순서에 의존하는 경우 문제가 될 수 있습니다.
- 몇몇 주요 기능들은 명시적으로 실험적(experimental) 단계입니다. 저장 시 암호화(encryption at rest), 증분 계산(incremental computation), 그리고 다중 프로세스 WAL 조정(multi-process WAL coordination)은 프로젝트 자체 문서에서도 모두 실험적 단계라는 라벨이 붙어 있습니다.
- 대부분의 경우 여전히 libSQL이 프로덕션용으로 권장됩니다. 유지 관리자들은 Rust 엔진이 빠르게 진화하고 있음에도 불구하고, libSQL은 프로덕션 준비가 된 상태인 반면 Rust 엔진은 그렇지 않다고 분명히 밝히고 있습니다.
이러한 점들이 프로젝트를 비하하는 것은 아닙니다. 이 프로젝트는 SQLite의 자체 바이트코드(bytecode) 출력을 호환성 검사 도구로 사용하여 공개 퍼징(public fuzzing)을 수행하며, 공개적으로 구축되고 있는 젊고 빠르게 움직이는 재작성 프로젝트입니다. 이는 진정으로 엄격한 접근 방식입니다. 다만 여기서 "베타"라는 용어는 단순히 형식적인 것이 아니라는 의미입니다.
시도해 볼 가치가 있을까요?
사이드 프로젝트, 프로토타입, 그리고 약간의 거친 부분이 있더라도 허용할 수 있는 모든 경우에는 시도해 볼 가치가 있습니다. 설정 비용은 거의 제로에 가깝습니다. 쉘 스크립트 하나면 충분하며, 서버도 필요 없고, 기존의 SQLite 지식을 대부분 그대로 활용할 수 있습니다. 만약 여러분의 워크로드가 빈번한 동시 쓰기(concurrent writes), 임베딩(embeddings) 및 벡터 검색(vector search)을 포함하거나, 단순히 SQLite가 다음 단계로 어디를 향하고 있는지 지켜보고 싶다면, 지금이 바로 성능을 테스트(kick the tires)해 보기 좋은 시기입니다.
이를 생각하는 합리적인 방법은 다음과 같습니다: Turso는 단순히 "또 하나의 데이터베이스"가 되려는 것이 아닙니다. Turso는 상당히 구체적인 질문에 답하고자 합니다. 즉, SQLite를 SQLite답게 만드는 요소를 잃지 않으면서도, SQLite의 단순함을 메모리 안전(memory-safe)하고, 비동기 네이티브(async-native)이며, 동시 쓰기(concurrent-write)가 가능한 환경으로 이어갈 수 있는가 하는 질문입니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기