궁금한 주제를 찾아보세요

비트코인, 스테이블코인, 온체인 데이터처럼 주제로 검색하세요.

다시 읽을 이야기

저장한 글은 이 브라우저에만 보관됩니다.

해설기술·생태계

EVM 체인 재구성 때 로그 인덱서가 되돌림을 처리하는 법

removed 로그, block hash, 확인 단계와 멱등 처리를 연결해 체인 재구성 뒤에도 파생 잔액과 주문 상태를 일관되게 유지하는 방법을 설명합니다.

난이도 중급주제 카테고리와 개념 밀도 기준검토 정보AI 보조 초안 · 출처 목록 제공 · 주장별 대조 진행 중
체인 분기에서 폐기된 기록을 되돌리고 새 정식 블록의 로그를 처리하는 재구성 대응 그림
주제의 이해를 돕기 위해 imagegen으로 제작한 AI 생성 개념 일러스트
먼저 읽는 핵심

로그 식별자는 transaction hash 하나가 아니라 block hash와 log index까지 포함합니다.
removed=true는 삭제 신호가 아니라 이전 적용 효과를 정확히 되돌릴 입력입니다.
구독 재연결 뒤에는 저장한 커서와 블록 해시를 대조하고 범위를 다시 조회합니다.

로그 인덱서는 이벤트를 받는 즉시 확정 사실로 덮어쓰지 말고 blockHash·blockNumber·transactionHash·logIndex와 함께 원본을 저장해야 합니다. 이미 처리한 로그가 removed=true로 다시 오면 그 로그가 만든 파생 효과를 역연산하고, 새 정식 체인의 로그를 멱등하게 적용합니다. WebSocket 구독은 연결이 끊긴 동안 과거 이벤트를 채워 주지 않으므로 마지막으로 연속 확인한 블록부터 eth_getLogs로 공백을 재조회해야 합니다. 화면의 빠른 상태, safe 상태, finalized 상태를 별도 단계로 운영하면 속도와 재구성 위험을 숨기지 않을 수 있습니다.

블록 높이는 같아도 정식 체인은 바뀔 수 있습니다

실행 클라이언트는 같은 높이에서 서로 다른 block hash를 관측할 수 있습니다. 예를 들어 높이 21,000,100의 A 블록에서 Deposit 로그를 받아 사용자 잔액을 5 ETH 올렸는데, 다음 head의 parentHash가 A가 아니라 다른 조상을 가리키면 A의 효과는 더 이상 정식 체인 상태가 아닐 수 있습니다. 블록 번호만 저장한 인덱서는 이 차이를 잡지 못합니다.

Geth의 logs 구독은 재구성으로 옛 체인에 남은 로그를 removed=true로 다시 보내고, 새 체인에 포함된 거래의 로그도 보냅니다. 같은 transaction이 여러 번 전달될 수 있으므로 **transactionHash만으로 중복 제거하지 않습니다**. 체인상의 위치를 나타내는 blockHash와 logIndex를 함께 보존해야 합니다.

재구성 대응은 로그를 지우는 예외 처리보다, 적용과 취소를 같은 수준의 상태 전이로 설계하는 일입니다.

JOBCOIN 해설

VISUAL GUIDE프로토콜 실행의 기본 구조
입력이 실행 규칙을 통과할 때 상태가 바뀌는 프로토콜 개념도
그림과 함께 짚어볼 본문 내용

그림은 이 주제의 공통 개념을 단순화한 설명입니다. 아래 항목에서 이 글의 구체적인 조건과 예외를 함께 읽어보세요.

  1. 블록 높이는 같아도 정식 체인은 바뀔 수 있습니다

    실행 클라이언트는 같은 높이에서 서로 다른 block hash를 관측할 수 있습니다.

  2. 원본 로그와 파생 상태를 분리합니다

    원본 event 테이블 에는 chainId, blockNumber, blockHash, transactionHash, transactionIndex, logIndex, address, topics, data와 removed 상태를 기록합니다.

  3. A 체인에서 B 체인으로 바뀌는 순서를 고정합니다

    높이 100의 블록 A가 Deposit 5와 OrderFilled 1을 포함했다고 가정합니다.

AI로 제작한 개념도 · 실제 가격·거래 내역·통계가 아닙니다.

원본 로그와 파생 상태를 분리합니다

원본 event 테이블에는 chainId, blockNumber, blockHash, transactionHash, transactionIndex, logIndex, address, topics, data와 removed 상태를 기록합니다. 파생 잔액·포지션·주문에는 어떤 원본 event가 만든 변화인지 연결합니다. 그러면 A 블록이 제거될 때 그 이벤트가 더한 5 ETH만 역분개하고 다른 입금은 건드리지 않을 수 있습니다.

상태 전이는 멱등해야 합니다. 같은 활성 로그가 재전송되면 두 번 더하지 않고, 이미 취소한 로그가 다시 removed로 와도 두 번 빼지 않습니다. 고유 키는 체인과 블록 위치를 반영하고 처리 결과와 원본 상태 변경을 한 데이터베이스 transaction에 묶습니다.

재구성 대응 데이터의 역할
데이터 저장 이유 재처리 동작
blockHash·parentHash 정식 연결 관계 확인 공통 조상까지 후퇴
txHash·logIndex 블록 안 로그 위치 식별 동일 위치 중복 방지
removed 상태 옛 체인 로그 판별 파생 효과 역분개
처리 커서 구독 공백 범위 결정 eth_getLogs로 재조회
확정 단계 노출 위험 전달 provisional·safe·finalized 분리

A 체인에서 B 체인으로 바뀌는 순서를 고정합니다

높이 100의 블록 A가 Deposit 5와 OrderFilled 1을 포함했다고 가정합니다. 인덱서는 두 로그를 provisional로 적용합니다. 이후 높이 100의 블록 B가 정식 연결에 들어오면 A의 두 로그를 역순으로 취소하고, B의 로그를 순서대로 적용합니다. 동일 거래가 B에도 들어갔더라도 block hash나 log index가 달라질 수 있어 새 위치의 이벤트로 취급합니다.

파생 작업도 함께 되돌릴 수 있어야 합니다. 외부 송금·이메일처럼 체인 상태를 넘어선 부작용을 provisional 로그 하나로 즉시 실행하면 데이터베이스 rollback만으로 복구되지 않습니다. 가치 이전은 요구 확정 단계 뒤에 실행하고, 빠른 알림에는 잠정 상태임을 표시합니다.

  • 새 head의 parentHash를 직전 정식 head hash와 비교합니다.
  • 불일치하면 저장한 조상 해시를 따라 공통 조상을 찾습니다.
  • 옛 가지 로그의 파생 효과를 역순으로 취소합니다.
  • 새 가지 블록과 receipt를 앞에서부터 검증해 적용합니다.
  • 마지막 연속 블록부터 범위 조회해 구독 공백을 메웁니다.
  • safe·finalized 경계가 전진하면 상태 라벨을 승격합니다.

확인 개수와 합의 확정성을 구분합니다

‘12 confirmations’ 같은 숫자는 애플리케이션이 head와의 거리로 만든 정책입니다. 자산 가치, 네트워크, 장애 시나리오에 따라 달라지며 그 자체가 합의 프로토콜의 finalized 판정은 아닙니다. Ethereum PoS에서 justified·finalized checkpoint는 validator vote와 epoch 규칙에 연결됩니다.

빠른 UI는 latest 근처를 provisional로 보여 주고, 출금 승인 같은 고위험 작업은 safe 또는 finalized 기준을 요구할 수 있습니다. RPC 제공자가 해당 태그를 지원하는지, execution client와 consensus client가 정상 동기화됐는지도 감시해야 합니다. **확인 깊이와 합의 확정성을 같은 숫자로 취급하지 않습니다**.

구독은 전달 채널이지 완전한 원장 복제 기능이 아닙니다

Geth 문서에 따르면 subscription은 연결에 결합되고 연결이 닫히면 사라집니다. 알림은 현재 이벤트용이며 과거 이벤트를 보충하지 않고, 소비자가 내부 buffer를 따라가지 못하면 연결이 닫힐 수도 있습니다. 재연결 성공만 보고 누락 없음으로 판단하면 안 됩니다.

운영자는 마지막으로 완전하게 처리한 block number와 hash를 영속화합니다. 재시작 때 현재 노드에서 그 hash가 같은 높이의 canonical block인지 확인한 뒤, 불일치하면 공통 조상까지 rewind합니다. 그 다음 작은 범위로 eth_getLogs를 반복 호출하고 실시간 구독과 겹치는 구간은 멱등 키로 합칩니다.

장애 연습은 실제 역분개 결과까지 확인합니다

개발망에서 블록 A 로그를 적용한 뒤 스냅샷 복귀나 대체 가지로 재구성을 만들고, removed 처리 전후 원본과 파생 잔액을 비교합니다. WebSocket을 끊은 사이 여러 블록을 만든 뒤 재연결해 누락 범위가 모두 보충되는지도 시험합니다.

관측 지표에는 head 지연, parent mismatch, rewind 깊이, removed 로그 수, backfill 범위, 중복 무시 수, safe·finalized 지연을 둡니다. 경보만 울리고 자동 rewind가 실패할 때를 위해 특정 block hash부터 재생하는 runbook과 대조 쿼리를 준비합니다.

자주 묻는 질문

removed=true인 로그를 데이터베이스에서 삭제하면 되나요?

감사와 멱등 처리를 위해 원본은 보존하고 removed 상태를 기록한 뒤, 연결된 파생 효과를 역분개하는 편이 안전합니다.

transaction hash는 왜 고유 키로 부족한가요?

재구성 뒤 같은 거래가 새 블록에 다시 포함되어 다른 block hash나 log index를 가질 수 있고 로그도 여러 개일 수 있기 때문입니다.

WebSocket을 재연결하면 놓친 로그가 자동으로 오나요?

Geth subscription은 과거 이벤트를 보충하지 않으므로 저장한 커서부터 eth_getLogs 범위 조회로 공백을 메워야 합니다.

더 깊이 읽기

본문에서 다룬 개념과 확인 절차를 다음 글에서 이어서 살펴보세요.

참고한 원문 자료

자료 확인 기준일 2026.09.27
  1. go-ethereum — Real-time Eventsgeth.ethereum.org
  2. ethereum.org — Proof-of-stakeethereum.org
자료 대조 기록과 확인 범위
출처 수집
원문 링크 2개 제공
핵심 주장 대조
완료 근거가 아직 기록되지 않았습니다.
분야 전문가 검수
별도 완료 기록이 없습니다.

원문 링크와 자료 확인일은 글 전체의 주장 대조나 전문가 검수 완료를 뜻하지 않습니다. 별도 확인이 필요한 절차는 원문의 적용 대상과 최신 안내를 함께 확인해 주세요.

AI 활용 안내

이 글은 초안 구성과 자료 정리에 AI를 활용했습니다. 글에 표시된 출처와 기준일을 함께 확인해 주세요. 별도 검토 정보가 없다면 전문가 검수를 뜻하지 않습니다.

이해를 위한 정보 콘텐츠

이 글은 특정 자산의 매수·매도 또는 수익을 권유하지 않습니다. 자료의 발표 시점과 이후 변경 사항을 함께 확인해 주세요.

편집 원칙 보기 →이 기사 정정 제보 →