블록체인 인덱서 가이드
인덱서는 원장 데이터를 제품 요구에 맞게 재구성해 저지연으로 제공하는 데이터 레이어임 디앱 체감 속도와 신뢰도를 좌우하는 핵심 인프라임
왜 인덱서가 필요한가
- 블록체인 원장은 블록 단위 직렬 구조라 임의 접근과 조건 검색 비용 큼
- 디앱은 지갑 이력, 포지션, 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
}
}
}
마무리
- 인덱서는 제품이 자주 묻는 질문을 데이터 구조로 먼저 표현하는 도구임
- 초기 단계에서 질의 패턴과 최종성 전략을 분명히 하고 재처리, 관측성, 비용의 트레이드오프를 문서화할 것
- 관리형 서비스와 자체 구축을 혼합해 민첩성과 통제력을 균형 있게 가져갈 것