블록체인 인덱서 가이드

인덱서는 원장 데이터를 제품 요구에 맞게 재구성해 저지연으로 제공하는 데이터 레이어임 디앱 체감 속도와 신뢰도를 좌우하는 핵심 인프라임


왜 인덱서가 필요한가

  • 블록체인 원장은 블록 단위 직렬 구조라 임의 접근과 조건 검색 비용 큼
  • 디앱은 지갑 이력, 포지션, NFT 보유 등 사용자 맥락 데이터를 수십~수백 ms 내에 필요로 함
  • 전체 원장을 매번 스캔하는 대신 목적형 보조 인덱스를 사전 구축해 API로 제공하는 전략이 효율적임

핵심 개념

인덱싱 대상 데이터 유형

  • 블록 헤더와 트랜잭션 메타데이터

    • 블록번호, 타임스탬프, 가스 사용량, 트랜잭션 해시 등
  • 스마트 컨트랙트 이벤트 로그

    • 토픽과 데이터 필드, 인덱스드 파라미터, 로그 인덱스 등
  • 컨트랙트 상태 스냅샷 또는 파생 지표

    • 잔액 스냅샷, 포지션 지표, 시계열 집계 등

용어 정리

  • 서브그래프

    • 특정 도메인을 위한 스키마형 인덱싱 단위
  • 최종성 Finality

    • 블록이 되돌려지지 않을 확률이 충분히 낮은 상태를 의미함
  • 재구성 Reorg

    • 더 긴 체인이 나타나 일부 블록이 교체되는 현상으로 인덱서가 롤백과 재처리를 수행해야 함
  • 백필 Backfill

    • 과거 블록 범위를 대량으로 인덱싱하는 작업이며 라이브 스트림과 병행 운영 필요함

아키텍처 구성 요소

  • 수집기 Ingestor

    • 풀노드 또는 게이트웨이에 구독 혹은 폴링으로 연결해 새 블록과 트랜잭션, 로그 수신
    • 블록 범위 큐와 재시도, 속도 제한 제어 포함 권장
  • 파서 Parser

    • ABI 기반 디코딩으로 이벤트와 함수 호출 입력을 구조화함
    • 주소, 체인ID, 블록번호, 트랜잭션 해시를 기본 정규화 키로 포함
  • 인덱서 Indexer

    • 예상 질의 패턴에 맞춘 보조 인덱스와 머티리얼라이즈드 뷰 생성
    • 멱등 처리로 중복 입력에 안전해야 함
  • 저장소 Storage

    • 관계형 SQL, 문서형, 키밸류, 시계열 중 워크로드에 맞게 혼합 선택
    • 쓰기 집중 구간과 읽기 집중 구간을 분리 설계 권장
  • 서비스 API

    • GraphQL 또는 REST 제공
    • 캐시, 커서 기반 페이지네이션, 레이트 리밋, 다중 리전 배포 포함 권장

동작 원리

1) 데이터 수집

  • 최신 블록 스트림 수신
  • 토픽 기반 필터로 관심 이벤트만 선별 가능
  • 블록 범위 작업 단위를 설정해 재시도와 병렬 처리 제어

2) 정리와 저장

  • ABI로 이벤트 파싱 후 표준 스키마로 정규화

  • 파티셔닝 키 설계 예시

    • 주소별 파티션, 컨트랙트별 파티션, 체인ID별 샤딩
  • 스토리지 선택 가이드

    • SQL은 조인과 강한 정합성 강점
    • NoSQL은 쓰기 성능과 수평 확장 강점
    • 혼합 접근으로 원본 로그 테이블과 조회 최적화 테이블을 분리

3) 제공과 캐싱

  • 핫 키에 인메모리 캐시와 세그먼트 캐시 적용
  • 커서 기반 페이지네이션으로 대량 스캔 방지
  • 지표성 데이터는 사전 집계 테이블이나 머티리얼라이즈드 뷰 사용

4) 최종성과 재처리

  • N 컨펌 이후 확정 마킹으로 Reorg 영향 최소화
  • Reorg 발생 시 영향 범위만 역인덱스 삭제 후 재인덱싱
  • 백필 잡과 라이브 스트림의 경계 관리로 중복 작업 방지

데이터 모델과 스키마 예시

원본 이벤트 로그 테이블 예시

CREATE TABLE ev_raw (
  chain_id INT NOT NULL,
  contract_address VARBINARY(20) NOT NULL,
  block_number BIGINT NOT NULL,
  block_time TIMESTAMP NOT NULL,
  tx_hash VARBINARY(32) NOT NULL,
  log_index INT NOT NULL,
  topic0 VARBINARY(32) NOT NULL,
  topic1 VARBINARY(32) NULL,
  topic2 VARBINARY(32) NULL,
  topic3 VARBINARY(32) NULL,
  data BLOB NOT NULL,
  PRIMARY KEY (chain_id, block_number, tx_hash, log_index)
)

조회 최적화 테이블 예시

CREATE TABLE nft_transfers (
  chain_id INT NOT NULL,
  contract_address VARBINARY(20) NOT NULL,
  token_id DECIMAL(78,0) NOT NULL,
  from_address VARBINARY(20) NOT NULL,
  to_address VARBINARY(20) NOT NULL,
  block_number BIGINT NOT NULL,
  block_time TIMESTAMP NOT NULL,
  tx_hash VARBINARY(32) NOT NULL,
  PRIMARY KEY (chain_id, contract_address, token_id, block_number, tx_hash),
  INDEX idx_owner_history (chain_id, to_address, block_number DESC)
)

GraphQL 질의 예시

query {
  transfers(first: 10, where: { from: "0xaaaa...", to: null }) {
    id
    from
    to
    value
    blockNumber
    txHash
  }
}

핵심은 애플리케이션이 자주 묻는 질문을 스키마와 인덱스로 선제 정의하는 것임 원장 재탐색 없이 즉시 응답 가능한 형태로 데이터를 재구성하는 것이 목표임


일관성 모델

  • 확정 상태와 미확정 상태를 명시 구분

    • 응답 필드에 finality_level 또는 confirmations 포함 권장
  • API 파라미터로 최종성 레벨 허용

    • 예시로 minConfirmations=12 전달 시 해당 기준 충족 데이터만 반환
  • 읽기 스냅샷 일관성 유지로 동일 요청 내 시간축 안정성 보장


재처리와 멱등성

  • 블록 범위 단위의 재인덱싱이 가능하도록 범위 메타 유지

  • 멱등 키 설계

    • (chain_id, tx_hash, log_index) 또는 이벤트 고유 해시로 중복 삽입 방지
  • 업서트 기반 로딩으로 재처리 안전성 확보

INSERT INTO nft_transfers (...)
VALUES (...)
ON DUPLICATE KEY UPDATE block_time = VALUES(block_time)

성능과 비용 최적화

  • 백필은 대역폭 우선, 라이브는 지연 우선으로 튜닝
  • 파티션 핫스팟 회피를 위해 주소 해싱 또는 범위 셔플링 적용
  • 대규모 이벤트의 경우 배치 크기와 커밋 간격을 체계적으로 설정
  • 스키마 버저닝을 통해 마이그레이션 시 이중 기록 전략 적용 권장

운영과 관측성

  • 필수 지표

    • 블록 지연, 수집 지연, 처리 라그, 오류율, 재시도율, 큐 적체량
  • 알람 기준

    • 라그 급증, Reorg 빈도 증가, 특정 컨트랙트 오류 급증
  • 롤백과 재시작

    • 저장소에 체크포인트와 커밋 오프셋 기록으로 안전 복구 가능하게 설계

보안과 무결성

  • 데이터 출처 이중화와 교차 검증 적용

    • 서로 다른 노드나 공급자에서 샘플 검증 수행 권장
  • 서명 검증 가능한 데이터는 파이프라인 내 즉시 검증

  • 민감 메타데이터는 암호화 저장과 접근 통제 적용


주요 플랫폼 비교 요약

  • The Graph

    • GraphQL 기반 서브그래프 모델과 커스텀 스키마, 매핑 지원
    • 이벤트 중심 도메인 모델링이 단순함
  • Covalent

    • 멀티체인 통합 API와 공통 스키마 제공
    • 빠른 프로토타이핑과 대시보드 연동 용이
  • QuickNode

    • 노드와 인덱싱 API 조합으로 고성능 엔드포인트 제공
  • Moralis

    • 멀티체인 디앱 백엔드 도구로 지갑과 NFT 중심 인덱싱 제공
  • 자체 구축

    • 유연성과 데이터 소유권 강점
    • 운영 복잡성과 비용 증가 단점 존재

대표 사용 사례

  • 지갑 화면에서 주소 기준 트랜잭션과 토큰 잔액 즉시 조회
  • 디파이 포지션 수익률과 담보 상태를 실시간 계산
  • NFT 소유 목록, 전송 이력, 메타데이터 동기화 제공
  • 온체인 데이터 기반 분석과 알림 트리거 생성

베스트 프랙티스 체크리스트

스키마 설계

  • 상위 핵심 질의 세 가지를 먼저 정하고 파티셔닝과 보조 인덱스를 결정
  • 원본 로그 테이블과 조회 최적화 테이블을 분리 운영
  • 시간 기반 파티셔닝과 주소 기반 인덱스를 함께 고려

재처리 전략

  • 블록 범위 메타를 보관해 부분 재인덱싱 가능하게 유지
  • 멱등 키와 업서트로 중복 삽입 방지

일관성과 최종성

  • 확정과 미확정 데이터를 응답에서 구분
  • API에 최종성 파라미터 제공

성능과 비용

  • 백필 파이프라인은 대역폭과 병렬성 극대화
  • 라이브 스트림은 지연과 안정성 최적화
  • 핫 파티션 회피를 위한 해싱 또는 샤딩 적용

운영과 관측성

  • 라그와 오류 지표를 1급 시민으로 모니터링
  • 스키마 버저닝과 롤백 계획을 문서화

보안과 무결성

  • 공급자 이중화와 교차검증 구성
  • 서명 검증 가능한 지표는 수집 단계에서 검증

안티 패턴

  • WHERE 절에 함수 연산을 남발해 인덱스를 무력화하는 패턴
  • 원본 로그 테이블 하나로만 모든 질의를 처리하려는 단일 스키마 고집
  • Reorg 가정 부재로 롤백 경로가 없는 파이프라인
  • 커서 대신 페이지 오프셋을 사용해 심각한 스캔을 유발하는 페이지네이션

간단 레퍼런스

  • 이더리움 JSON-RPC eth_getLogs로 토픽 필터링 수집 가능
  • Solidity 이벤트는 ABI로 디코딩해 구조화 가능
  • GraphQL은 선택적 필드 조회와 관계 탐색에 유리함
query WalletView($owner: String!, $first: Int!, $cursor: String) {
  erc20Balances(owner: $owner, first: $first, after: $cursor) {
    edges {
      node {
        contract
        symbol
        decimals
        balance
        updatedAt
      }
      cursor
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

마무리

  • 인덱서는 제품이 자주 묻는 질문을 데이터 구조로 먼저 표현하는 도구임
  • 초기 단계에서 질의 패턴과 최종성 전략을 분명히 하고 재처리, 관측성, 비용의 트레이드오프를 문서화할 것
  • 관리형 서비스와 자체 구축을 혼합해 민첩성과 통제력을 균형 있게 가져갈 것

참고자료