요약
rqlite 개발자가 2014년부터 12년간 이어진 분산 SQLite의 계보를 정리했습니다.
rqlite를 만든 필립 오툴의 글입니다. 이 분야의 역사는 흔히 2021년 무렵부터 이야기되지만, 그는 2014년 rqlite에서 시작하는 역사를 기록으로 남기고 싶다고 했습니다.
왜 중요한가
- 프로젝트마다 대비하려는 장애가 다르다는 점을 보여 줍니다. 그래서 고르는 기준은 성능보다 자기가 던지는 질문이라는 정리입니다.
- 이 발상은 8년 동안 오픈소스로만 있었습니다. 돈은 이를 유료 서비스로 만든 플랫폼이 벌었다고 짚었습니다.
핵심 내용
- rqlite는 SQLite 앞에 Raft 로그(노드끼리 합의해 쓰기 순서를 맞추는 기록)를 두어 모든 쓰기를 클러스터에 복제합니다.
- 리더가 쓰기를 받고 과반이 확인해야 반영하는 CP(일관성 우선) 설계는 처음부터 바뀌지 않았습니다.
- 이 분야를 합의(rqlite, dqlite), 스트리밍(Litestream), 병합(cr-sqlite)의 세 갈래로 나눴습니다.
- Litestream은 서버가 죽는 경우를, rqlite는 서버가 죽었는데 복구를 기다릴 수 없는 경우를 겨냥한다고 했습니다.
- 캐노니컬의 dqlite, libSQL을 바탕으로 한 Turso 등 적어도 여덟 팀이 같은 발상을 다시 만들어 냈습니다.
HN 반응
- 일부 이용자는 rqlite가 BEGIN/COMMIT 트랜잭션을 공식 지원하지 않는다며, 트랜잭션 지원 여부가 중요한 비교 기준이라고 보충했습니다.
- 글이 AI가 쓴 문체 같다는 비판이 여러 댓글에서 나왔고, 전혀 그렇게 느끼지 않았다는 반론도 있었습니다.
D1을 프로덕션에서 써 봤는데, 그다지 믿을 만하지 않습니다. HN에 D1 개발자 중 한 명이 남긴 댓글[1]이 있는데, D1은 Durable Objects 위에 얹은 SQL 래퍼일 뿐이고 분산 SQLite처럼 보이게 흉내 낸 것이라고 합니다.
[1] https://news.ycombinator.com/item?id=48611834
D1은 읽기 복제와 특정 시점 복구(PITR)도 제공합니다. 다만 저한테 가장 큰 문제는 Durable Objects처럼 D1 데이터베이스를 동적으로 만들 수 없다는 점입니다. 그래서 멀티테넌시 같은 걸 구현하기가 더 어렵습니다.
Durable Objects는 좀... 독점 기술 아닌가요? 특정 클라우드 플랫폼에 묶여 있잖아요?
이제는 아닙니다. celld를 보세요. https://news.ycombinator.com/item?id=50020200
완전히 동의합니다. D1은 진짜 불안정해요!
이런 엔진을 전부 모아서 외부 의존성, 리더 하나만 쓸 수 있는지 아니면 어느 노드든 쓸 수 있는지, 형태(임베디드 라이브러리인지 서버인지) 같은 항목별로 비교한 표가 있으면 좋겠습니다.
개인적으로는 트랜잭션 지원 여부가 꽤 중요한 분기점이라고 봅니다. SQLite 트랜잭션을 완전히 지원하는 엔진도 있지만, rqlite처럼 BEGIN/COMMIT을 공식적으로 지원하지 않는 엔진도 있습니다[0]. 여러 문장으로 이루어진 트랜잭션에 의존한다면 이 차이가 중요합니다.
제 친구이자 동료가 dqlite용 순수 Python 클라이언트(DB-API와 SQLAlchemy)를 만들고 있는데[1], 여기 계신 분들이 관심 가질 만할 것 같습니다. dqlite는 트랜잭션을 완전히 지원하고, rqlite처럼 외부 의존성(S3나 Consul 같은 것)이 없습니다.
rqlite나 다른 엔진을 깎아내리려는 건 아닙니다. dqlite에도 흠은 있습니다[2].
[0] https://rqlite.io/docs/faq/#does-rqlite-support-transactions
[1] https://github.com/letsdiscodev/python-dqlite-dbapi
[2] https://github.com/canonical/dqlite/issues/882 (제 친구가 올림), https://github.com/canonical/dqlite/issues/908 , https://github.com/canonical/dqlite/issues/912 (제가 올림)
재미있네요. 저는 Part-Time Parliament 논문(Paxos)을 읽으면서 Zig와 Odin을 배우던 중에 순수 Paxos 라이브러리를 만들었고, 그 라이브러리의 첫 번째 응용으로 멀티 마스터 SQLite를 만들었습니다. 두 가지 접근은 서로 많이 다릅니다. Zig로는 zaxonlite( https://github.com/insanai/zaxonlite )를 만들었고, rqlite가 포함된 벤치마크도 있습니다. 복제 전략으로 WAL 복제를 씁니다. Odin으로 시도한 두 번째는 sqlodin( https://github.com/insanai/sqlodin )인데, 이쪽은 WAL을 쓰지 않고 각 노드에서 SQL 쿼리를 직접 실행하기 때문에 SQLite의 SQL 쿼리 중 일부는 지원하지 않습니다.
와, 비교적 신생 프로젝트에 155쪽짜리 책이라니 흥미롭네요. 작업은 어떤 흐름으로 하셨나요? 대부분 생성된 것처럼 보이는데, 새 기능을 작업할 때 이 책 전체를 최상위 에이전트의 컨텍스트로 쓰시나요, 아니면 관련된 부분만 발췌해서 쓰게 하시나요? PDF로 출력한 이유는 뭔가요? (보기에는 좋네요.)
저는 SQLite와 그 단순함을 좋아했던 사람인데, 에이전트를 쓰고 나서 보니 Postgres를 관리하는 일이 아주 쉬워졌습니다. 게다가 Postgres의 SQL 기능을 전부 쓸 수 있다는 점이 정말 좋습니다. SQLite는 SQL 면에서 제약이 많거든요. 그러니 원격 SQLite 같은 걸 고민 중이라면, 지금이 그냥 데이터베이스 서버를 쓰기에 그 어느 때보다 좋은 때인 것 같습니다. 물론 SQLite는 로컬 도구 같은 데는 훌륭합니다.
문제는 "원격" SQLite입니다. 프로세스 안에서 돌아가는 SQLite를 쓰고 Litestream으로 오브젝트 스토리지에 백업하는, 성능 좋은 "단일" 서버 한 대만 돌리면 RDBMS 걱정은 다시는 안 해도 됩니다. 애플리케이션의 90% 이상은 이 설계가 더 잘 맞고, 더 빠르고, 더 쌀 거라고 장담합니다.
저는 100달러도 안 되는 서버에서 초당 20만 건쯤 처리합니다. https://github.com/pairshaped/gleam_sqlite_benchmarks/blob/master/REPORT.md
에이전트가 어떻게 도움이 되나요? 전에는 Postgres의 뭐가 문제였는데요?
제 추측이지만, 코딩 에이전트가 깊이 있는 문서와 고급 패턴을 직접 다 뒤지는 것보다 더 잘, 적어도 더 빨리 보여 주기 때문이 아닐까요.
저도 똑같이 느꼈습니다. 예전에는 SQLite를 좋아하는 마음이 그 정체에 비해 거의 비이성적일 정도라는 생각을 자주 했습니다. 지금은 프로젝트 몇 개에서 LLM에게 Postgres를 맡겼는데, 데이터베이스 서버의 골치 아픈 부분을 대부분 알아서 처리해 주니 정말 좋습니다. 임베디드 환경이나 호스팅 서버가 없는 경우에는 여전히 SQLite를 고릅니다.
휴대폰에서 임베디드 Postgres를 쓸 수 있게 되는 날이 오면 참 좋겠네요.
rqlite와 Litestream을 비롯해 여러 프로젝트를 비교한 부분이 흥미로웠습니다. (rqlite는 노드 간에 합의 알고리즘을 써서 동기화를 유지하고 프라이머리 노드를 바꿀 수 있게 하는 반면, Litestream은 자기 자신을 S3에 동기화할 뿐이라 다른 노드가 거기 있는 데이터로 이어받을 수 있습니다.)
글이 곧 D1을 다루면서, D1이 기반으로 삼는 Cloudflare Durable Objects와 D1의 관계가 Durable Objects를 오픈소스로 다시 구현해 S3에 쓰는 celld와 거의 같은 관계라고 언급할 줄 알았습니다. 그런데 글은 D1을 갑자기 비꼬듯이 시큰둥하게 다루고 넘어가고, 마지막 절은 rqlite를 감싸는 데 급급하고 패배주의적이라 어색합니다.
자기 경험을 자기 목소리로 쓰는 데서 아무 즐거움도 못 느낀다면, 대체 왜 굳이 쓰는 걸까요?
솔직히 프로젝트 이야기가 기본 설정 그대로의 클로드 말투로 쓰여 있으면 좀 거슬리죠.
저는 이 블로그 글에서 LLM 느낌이 전혀 안 나는데요.
제 눈에는 그런 느낌으로 가득합니다. (Pangram도 같은 판정을 내려서 글 전체를 AI 생성물로 표시합니다.)
(위 문장은 Claude Opus 4.8과 5.0에서 아주 전형적으로 나옵니다.)
(무슨 순서요? 이 설계 공간의 세 모서리는 바로 다음 문장에 가서야 나오는데, 그것들에는 다른 자연스러운 순서가 없습니다. 이렇게 엉뚱한 곳에 부리는 멋은 LLM의 전형적인 특징 같습니다.)
네, 저도 클로드가 쓴 슬롭 같았고, 선택도 참 이상하다고 생각했어요. 어쩌면 그분이 말로 불러 주고 클로드한테 글로 정리하게 했을 수도 있죠. 시간은 아끼겠지만, 그래도 이건 좀 아니죠.
저처럼 어쩔 수 없이 하루 종일 매일 클로드랑 대화하다 보면, 누가 봐도 티가 납니다.
부럽네요. 좋든 싫든 올해 제가 가장 많이 읽은 저자는 클로드입니다. 글을 보면 알아볼 수 있을 만큼 잘 아는 사람 저자는 몇 명 안 됩니다. LLM은 사람보다 훨씬 쉽습니다. 요즘 세대의 LLM은 문체를 바꾸는 데 완전히 무능해 보이니까요.
이걸 전부 한꺼번에 해 주는 프로젝트가 있나요?
SQLite처럼 임베디드로 쓸 수 있고
dqlite처럼 클러스터링이 되고
rqlite처럼 단독 노드로 돌릴 수 있고
litestream처럼 S3에 백업할 수 있고
cr-sqlite처럼 AP도 선택할 수 있으면서 CP도 함께 지원하는
https://github.com/punnerud/mpedb 는 아직 거기까지는 못 갔습니다. sqlite3, Postgresql, Oracle 간의 동기화에 초점을 맞추고 있습니다. sqlite3에서도 Postgresql 수준의 속도로 동시 쓰기가 가능하다는 것을 보여 줬습니다. (제가 만든 프로젝트입니다)
Apache Ignite 2.x와 꽤 비슷하게 들리네요. SQLite만큼 완성도가 높지는 않지만요.
임베디드로 쓸 수는 절대 없겠죠?
Java 의존성 묶음이라서, 데이터를 가진 Ignite 노드 전체를 Java 모놀리식 앱이나 마이크로서비스의 프로세스 안에 기꺼이 넣을 수 있습니다. .Net이나 다른 언어용 바인딩도 있지만 JVM만큼 매끄럽지는 않습니다.
이걸 자세히 들여다본 적은 한 번도 없었습니다. 대다수 클러스터형 데이터베이스 아키텍처보다 훨씬 쉬워 보이네요.
https://rqlite.io/
컨트롤 레이어에 쓰고 있는데 지금까지는 꽤 만족합니다.
로컬 rqlite에 쿼리할 수 있나요, 아니면 항상 리더로 가야 하나요?