A
Aura Core Research FORMAL VERIFICATION & LEDGERS
AURA CORE ARCHITECTURE #16 Storage & Performance • 8 min read

RAM 한계를 돌파하는 원장 스토리지: UTxO-HD와 순수 함수형 LSM 트리 스냅샷 아키텍처

거대해진 온체인 원장 상태를 전량 RAM에 상주시키던 기존 노드의 메모리 고갈 한계를 극복하고, 디스크 기반 LSM 트리와 불변 스냅샷으로 무중단 상태 복구를 달성하는 스토리지 엔진 분석

블록체인 성장이 초래한 '인메모리 원장'의 역설

블록체인 네트워크가 성숙하여 수천만 개의 활성 지갑과 수억 건의 토큰 계약을 품게 되면, 합의 알고리즘보다 먼저 비명을 지르는 영역은 원장 상태 스토리지(Ledger State Storage)입니다. 초기 지분 증명(PoS) 노드 아키텍처는 초고속 트랜잭션 검증을 위해 현재 활성화된 모든 UTxO 집합을 물리 메모리(RAM)에 전량 상주시키는 인메모리 전략을 택했습니다.

체인 초기에는 이 방식이 압도적인 조회 속도를 보장했습니다. 그러나 원장 크기가 수십 기가바이트를 넘어서면서 세 가지 심각한 운영 위기가 현실화되었습니다.

  1. 하드웨어 진입장벽의 급등: 검증 노드를 구동하기 위해 64GB~128GB 이상의 고사양 ECC RAM이 필수 조건이 되면서, 개인이나 소규모 커뮤니티가 운영하는 독립 노드가 탈락하고 대형 클라우드 데이터센터로 노드가 집중되는 중앙화 압력이 발생했습니다.
  2. 스냅샷 직렬화 시점의 합의 지연(Stop-the-World): 노드가 재부팅 후 빠르게 복구할 수 있도록 주기적으로 메모리 상태를 디스크에 덤프(Snapshot)할 때, 수천만 개의 객체를 직렬화하는 동안 가비지 컬렉션(GC) 부하가 폭증하여 슬롯 리더가 블록 생성 타이밍을 놓치는 현상이 나타났습니다.
  3. OOM(Out-of-Memory) 크래시와 긴 복구 시간: 예기치 않은 트래픽 폭주로 메모리가 고갈되어 프로세스가 강제 종료되면, 마지막 스냅샷 시점부터 수만 개의 블록을 다시 재생(Replay)하느라 노드가 수 시간 동안 합의에서 이탈했습니다.

5세대 블록체인 Aura는 카르다노의 UTxO-HD(High Density) 설계 사상을 순수 함수형으로 재해석하여, 활성 데이터는 메모리에 두되 방대한 전체 원장은 디스크 기반 로그 구조 병합 트리(LSM-Tree, Log-Structured Merge-Tree)로 분산 관리하는 스토리지 계층을 도입했습니다.

왜 B-Tree가 아닌 LSM-Tree인가?

전통적인 관계형 데이터베이스나 이더리움의 머클 패트리샤 트라이(MPT)가 주로 활용하는 B-Tree 계열 구조는 데이터를 디스크의 제자리에서 갱신(In-Place Update)합니다. 블록체인처럼 매 블록마다 수천 개의 UTxO가 무작위 해시 키 위치에서 생성되고 소멸하는 워크로드에서는, B-Tree의 랜덤 디스크 쓰기(Random Write)가 극심한 I/O 병목과 쓰기 증폭(Write Amplification)을 유발합니다.

반면 LSM-Tree는 모든 상태 변경을 불변의 추가 전용(Append-Only) 로그로 처리합니다. 이는 불변성(Immutability)을 핵심 가치로 삼는 순수 함수형 언어 하스켈의 데이터 모델과 구조적으로 완벽히 맞물립니다.

[ 신규 블록 검증 완료 (Diff: 소비된 UTxO 삭제표시 + 신규 UTxO 생성) ]
│
▼
┌──────────────────────────────────────────────────────────────────┐
│ 1. In-Memory Diff & MemTable (최신 2,160 슬롯 휘발성 구간)       │
│ • 체인 롤백(Rollback)이 발생할 수 있는 최근 블록들의 차분 보관     │
│ • O(log M) 인메모리 조회로 즉각적인 포크 전환 지원                 │
└─────────────────────────────────┬────────────────────────────────┘
                                  │ (안정성 윈도우 k 초과 시 불변 플러시)
                                  ▼
┌──────────────────────────────────────────────────────────────────┐
│ 2. Disk-Backed Immutable SSTables (Level 0 ──▶ Level 1 ──▶ L_n)  │
│ • 정렬된 키-값 불변 파일로 순차 쓰기(Sequential Write)             │
│ • 백그라운드 콤팩션(Compaction)으로 만료된 UTxO 물리적 회수       │
└──────────────────────────────────────────────────────────────────┘

롤백 구간과 확정 구간의 분리

우로보로스 합의에서 체인 포크로 인해 되돌려질 가능성이 있는 구간은 최신 k개 블록(안정성 윈도우)으로 엄격히 제한됩니다. Aura 스토리지 엔진은 이 최근 k개 블록의 상태 변화분(Ledger Diff)만 가벼운 인메모리 테이블에 유지하고, 이미 확정된 과거 원장은 디스크의 불변 SSTable(Sorted String Table) 계층으로 내립니다.

결과적으로 노드 구동에 필요한 RAM 점유량을 기존 대비 70% 이상 절감하면서도 검증 속도를 유지할 수 있습니다.

순수 함수형 스냅샷과 콤팩션 상태 머신

디스크 I/O 자체는 부수 효과(Side Effect)를 동반하지만, 언제 메모리 테이블을 플러시하고 어떤 SSTable들을 병합(Compaction)할지 결정하는 스케줄링 로직은 100% 순수 함수로 분리할 수 있습니다.

아래는 불변 원장 차분(Diff)을 누적하고 스냅샷 정책을 결정하는 핵심 상태 전이 인터페이스입니다.

{-# LANGUAGE StrictData #-}
module AuraLedgerStateSnapshot
    ( DiffEntry(..)
    , LedgerDiff
    , SSTableMeta(..)
    , StorageAction(..)
    , commitBlockDiff
    ) where

import qualified Data.Map.Strict as Map
import Data.Word (Word64)
import CardanoStateMachine (TxIn, TxOut)

-- 원장 상태의 원자적 변화: 신규 생성(Insert) 또는 소비 완료 표식(Tombstone)
data DiffEntry
    = InsertUTxO TxOut
    | DeleteUTxO
    deriving (Eq, Show)

type LedgerDiff = Map.Map TxIn DiffEntry

data SSTableMeta = SSTableMeta
    { tableId        :: Word64
    , tableLevel     :: Int
    , tableByteSize  :: Word64
    , tableSlotRange :: (Word64, Word64)
    } deriving (Eq, Show)

-- 순수 스토리지 엔진이 디스크 실행기에게 위임하는 불변 I/O 지시어
data StorageAction
    = FlushMemTableToL0 Word64 LedgerDiff
    | MergeSSTables [SSTableMeta] Int
    | PruneTombstones Word64
    deriving (Eq, Show)

-- 블록 확정 시 차분을 병합하고 임계치 초과 시 비동기 플러시 액션을 도출하는 순수 함수
commitBlockDiff
    :: Word64        -- ^ 현재 슬롯 번호
    -> Int           -- ^ 메모리 최대 유지 엔트리 수 (임계치)
    -> LedgerDiff    -- ^ 현재 활성 메모리 차분
    -> LedgerDiff    -- ^ 신규 블록에서 발생한 차분
    -> (LedgerDiff, [StorageAction])
commitBlockDiff currentSlot maxMemEntries activeMemDiff newBlockDiff =
    let merged = Map.union newBlockDiff activeMemDiff
    in if Map.size merged >= maxMemEntries
       then (Map.empty, [FlushMemTableToL0 currentSlot merged])
       else (merged, [])

commitBlockDiff 함수는 디스크 파일 핸들을 직접 열지 않습니다. 대신 새롭게 병합된 메모리 차분과 실행해야 할 StorageAction 목록을 순수 값으로 반환합니다. 만약 체인 포크가 발생해 블록을 롤백해야 한다면, 디스크의 SSTable을 건드릴 필요 없이 메모리 상의 LedgerDiff 맵 포인터만 이전 슬롯 버전으로 되돌리면 되므로 롤백 소요 시간이 O(1)로 수렴합니다.

백그라운드 콤팩션과 삭제 표식(Tombstone)의 수학적 소멸

eUTxO 원장의 고유한 특성은 한 번 생성된 UTxO가 소비되면 다시는 수정되지 않고 영구히 삭제된다는 점입니다. 일반적인 데이터베이스와 달리 과거 버전을 보존할 필요가 없으므로, 소비된 UTxO에 부여된 DeleteUTxO 표식(Tombstone)이 하위 레벨의 원본 InsertUTxO 엔트리와 콤팩션 과정에서 만나는 순간 두 레코드는 서로 상쇄되어 디스크에서 완전히 소멸합니다.

이 상쇄 메커니즘 덕분에 네트워크에서 수억 건의 트랜잭션이 처리되더라도, 디스크에 저장되는 실제 원장 용량은 누적 트랜잭션 수가 아니라 현재 시점에 실제로 존재하는 활성 UTxO의 수에만 비례하여 일정하게 유지됩니다.

저사양 자율 에이전트 노드를 위한 의의

5세대 블록체인 생태계에서는 클라우드 대형 서버뿐만 아니라 로컬 엣지 서버와 개인용 미니 PC에서 구동되는 수많은 자율 AI 에이전트들이 직접 원장을 검증해야 합니다. LSM 트리 기반 스냅샷 아키텍처는 하드웨어 스펙의 벽을 허물어, 제한된 메모리 환경에서도 풀 노드 수준의 암호학적 무결성을 유지한 채 무중단으로 합의에 참여할 수 있는 물리적 토대를 제공합니다.