coredot.today
기술 탐색으로 돌아가기
인프라·DB성장

TigerBeetle

시간·디스크·네트워크를 전부 가짜로 만들고 씨앗 하나로 버그를 되살린다 — 결정론적 시뮬레이션 테스트로 검증하는 금융 원장 데이터베이스

직접 해보기 4빠른 시작
종류
오픈소스
라이선스
Apache-2.0
언어
Zig
사실 확인
2026.10.24
curl -Lo tigerbeetle.zip https://linux.tigerbeetle.com && unzip tigerbeetle.zip

TRY IT

직접 해보기

OVERVIEW

개요

무엇인가

TigerBeetle은 금융 거래 전용 분산 데이터베이스입니다. 스키마는 계정(Account)과 이체(Transfer) 둘뿐이고, 모든 이체는 한 계정에서 다른 계정으로 가치가 옮겨 간 기록, 곧 복식부기입니다. 이체는 불변이라 잘못된 이체는 고치지 않고 반대 방향 이체를 하나 더 적습니다. 2020년에 시작됐고 소스는 Zig 약 15만 줄로 Apache 2.0에 공개돼 있습니다.

그런데 이 항목의 주인공은 데이터베이스보다 그것을 검증하는 방법입니다. 분산 시스템의 버그는 고치기보다 재현하기가 어렵습니다. 스위치가 30초 이상했고 디스크가 재시도했고 시계가 어긋났던 그 순간을 다시 만들 수 없기 때문입니다. TigerBeetle은 세상을 통째로 가짜로 만들어 이 문제를 풉니다. 시간은 정수 카운터, 디스크는 메모리 배열, 네트워크는 큐, 난수는 씨앗 하나에서 뽑습니다. 그러면 실행 전체가 정수 하나로 결정되고, 그 정수만 적어 두면 누구의 노트북에서든 같은 우주가 되살아납니다. 이것이 결정론적 시뮬레이션 테스트(DST)입니다.

어떻게 동작하나

시뮬레이터의 이름은 VOPR(Viewstamped Operation Replicator)입니다. 영화 워게임의 슈퍼컴퓨터 WOPR에서 따왔습니다.

1. 비결정성 걷어 내기
상태 기계는 운영체제에 시간을 묻지 못한다. 프라이머리가 요청을 프리페어로 바꿀 때 타임스탬프를 주입한다. 시뮬레이션의 시간은 ticks × resolution, 곱셈 한 번이다.
2. 결함 주입
패킷 손실·중복, 디스크 읽기·쓰기 고장, 엉뚱한 위치에 쓰는 오배치 쓰기, 네 가지 시계 어긋남, 크래시·재시작, 리플리카마다 다른 버전을 돌리는 롤링 업그레이드까지 섞는다.
3. 스웜 테스팅
결함 파라미터마저 씨앗에서 뽑는다. 리플리카 1~6대, 패킷 손실 0~30%처럼 매 씨앗이 다른 설정 조합이 된다. 고정 설정이 영원히 밟지 않는 경로를 밟게 하려는 것이다.
4. 단언이 잡는다
잘못된 상태를 알아채는 것은 단언이다. 프로덕션에서도 켜 둔다. 잔액을 틀리게 계산하며 도는 것보다 멈추는 것이 낫다는 판단이다.

코어닷투데이가 2026년 8월 저장소를 세어 보니 Zig 154,770줄, 함수 4,085개, assert 호출 8,180개로 함수당 정확히 2.00개였습니다. TigerStyle(팀의 엔지니어링 규칙)의 "함수당 평균 최소 두 개"가 문서에만 있는 규칙이 아니라는 뜻입니다.

설계에도 같은 태도가 깔려 있습니다. 시작 뒤에는 메모리를 할당하지 않고(정적 할당), 블록의 체크섬은 그 블록을 가리키는 부모가 들고 있어 엉뚱한 자리의 데이터를 바로 잡아내며, 리플리카의 데이터 파일은 바이트 단위로 같아 손상된 블록 하나만 옆에서 받아 옵니다. 클러스터는 6대를 권장하는데, 커밋은 3대 확인으로 하고 프라이머리 교체 때는 4대를 모아 두 집합이 반드시 겹치게 합니다(유연한 쿼럼). 이 교집합 성질도 주석이 아니라 런타임 단언으로 박혀 있습니다.

문서에 따르면 VOPR 함대는 1,024코어에서 24시간 내내 최신 main을 퍼징하고, 실패한 씨앗은 따로 기록해 회귀 테스트가 됩니다. 브라우저에서 결함을 던져 볼 수 있는 sim.tigerbeetle.com도 있습니다.

빠른 시작

README의 단일 리플리카 클러스터입니다(리눅스 기준, 다른 플랫폼은 docs.tigerbeetle.com/start).

bash
curl -Lo tigerbeetle.zip https://linux.tigerbeetle.com && unzip tigerbeetle.zip
./tigerbeetle format --cluster=0 --replica=0 --replica-count=1 --development 0_0.tigerbeetle
./tigerbeetle start --addresses=3000 --development 0_0.tigerbeetle

# 다른 터미널에서
./tigerbeetle repl --cluster=0 --addresses=3000
# > create_accounts id=1 code=10 ledger=700, id=2 code=10 ledger=700;
# > create_transfers id=1 debit_account_id=1 credit_account_id=2 amount=10 ledger=700 code=10;
# > lookup_accounts id=1, id=2;

시뮬레이터를 직접 돌리려면 저장소를 받아 씨앗 하나를 줍니다. 저장소가 Zig 컴파일러 버전을 직접 고정합니다.

bash
git clone https://github.com/tigerbeetle/tigerbeetle && cd tigerbeetle
./zig/download.sh
./zig/zig build vopr -- 123     # 씨앗 123으로 클러스터 하나를 시뮬레이션

언제 쓰고, 언제 피하나

상황TigerBeetle이 맞는다다른 방법을 먼저 본다
워크로드쓰기 위주, 수익 계정 같은 핫 계정에 경합이 몰리는 거래 기록읽기 위주, 복잡한 조인과 임의 질의
데이터가치의 이동으로 모델링되는 것 — 결제·정산·포인트·크레딧·API 과금사용자 프로필·상품 카탈로그처럼 자주 안 바뀌는 일반 데이터
역할일반 DB 옆에 두는 원장 전용 엔진, user_data 필드로 연결일반 DB를 대체하려는 시도
운영리눅스 · io_uring · 6대 구성이 가능한 환경서버리스·관리형만 쓰는 환경 (관리형 서비스는 별도)

데이터베이스를 쓰지 않더라도 방법론은 가져올 수 있습니다. 코드에서 now()를 직접 부르지 않고 주입받기, 전역 난수 대신 씨앗을 받은 PRNG 쓰기, 실패한 씨앗을 회귀 테스트로 승격하기는 비용이 낮고 대부분의 DST가 여기서 시작합니다. 에이전트가 하루에 수천 줄을 만드는 지금은 "같은 우주에서 반복 검증"하는 능력과, 사람이 다 읽지 못한 코드에서 계약 위반을 잡는 단언의 값이 더 커졌습니다.

한계와 주의

  • 시뮬레이션은 상태 공간을 탐색할 뿐 정의하지 않는다. 2025년 6월 Jepsen이 0.16.11을 분석해 안전성 문제 두 건을 찾았는데, 그중 하나는 VOPR의 워크로드 생성기가 지나치게 잘 짜여 두 인덱스가 늘 맞춰져 있던 탓에 지그재그 병합 조인의 한 경로를 한 번도 밟지 않아서 생겼습니다. 커버리지 지표로도 보이지 않는 사각지대였습니다.
  • '하루에 2천 년'은 어림 곱셈이다. 1,024코어 × 700배 가속 × 24시간이고, 한 클러스터의 2천 년이 아니라 여러 클러스터의 짧은 생애를 합친 값입니다.
  • 의도적으로 다루지 않는 결함이 있다. 오배치 쓰기는 저장소당 하나만 주입합니다. 이중 결함은 결함 모델 밖이라고 소스 주석에 적혀 있습니다.
  • 함수당 단언 두 개, 의존성 최소화, 함수 70줄 제한은 대부분의 팀에 과하다. 전부 따라 하기보다 돈·재고·권한처럼 틀리면 안 되는 곳의 불변식부터 단언으로 바꾸는 편이 현실적입니다.
  • 형식 검증(TLA+)은 알고리즘을, 결정론적 시뮬레이션은 구현을, Jepsen 같은 외부 검증은 내부 가정 바깥을 봅니다. 셋은 경쟁이 아니라 서로의 사각지대를 덮는 관계입니다.

DEEP DIVE

더 깊이 읽기