블록체인 TPS와 지연을 분석하는 벤치마크 프레임워크
블록체인 TPS 벤치마킹과 포함·최종성 지연 분석, 합의·네트워크·스토리지 병목 진단 방법을 정리한다.
2026-08-14 · 최초 발행 2025-10-31
처리율 뒤에 숨어 있는 지연과 병목
퍼블릭 체인과 프라이빗 체인 모두에서 성능 한계는 사용자 경험과 비용 구조에 직접 연결된다. 처리량을 측정할 때는 TPS만 보지 말고, 트랜잭션이 노드에 도착한 뒤 블록에 포함되고 최종성에 이르는 경로를 나누어 봐야 한다.
TPS(Tx/s)는 관측 구간 동안 커밋된 트랜잭션 수를 시간으로 나눈 처리율이다. 다만 체인마다 합의와 최종성 모델이 다르므로 블록 포함을 기준으로 삼는지, 확인 수 또는 BFT 커밋까지 완료된 트랜잭션만 집계하는지부터 명확히 해야 한다.
지연은 다음 흐름으로 분해한다.
- 제출 지연: 클라이언트에서 노드가 트랜잭션을 수신할 때까지의 왕복 지연
- 포함 지연: Mempool 대기부터 블록 포함까지의 시간
- 최종성 지연: 블록 생성 뒤 합의 또는 확정까지 걸리는 시간
병목은 보통 합의, 네트워크, 상태 및 스토리지 I/O에서 발생한다. 투표 라운드·리더 선출·슬롯 또는 에폭 파라미터는 합의 오버헤드에 속하고, 블록 및 가십 전파·RTT·대역폭·피어 토폴로지는 네트워크 요인이다. 상태 증분, DB write amplification, 스냅샷과 프루닝은 스토리지 계층을 살펴볼 때의 대상이다.
워밍업과 정상 상태를 분리하고, 오픈루프와 클로즈드루프 부하 모델도 구분한다. 중앙값만으로 판단하지 않고 p95와 p99 같은 꼬리 지연을 함께 기록해야 한다.
측정 환경과 부하를 먼저 고정한다
워크로드 제너레이터에서는 트랜잭션 생성률, 페이로드, 수수료 정책을 통제한다. 노드와 클라이언트의 시계 오차는 NTP/PTP 기반으로 < 5ms를 유지하며, Prometheus/OpenTelemetry로 노드·합의·네트워크·DB 계층의 메트릭을 수집한다.
시나리오는 전송형(transfer), 컨트랙트 호출형(mix), 읽기/쓰기 비율, 가스 소비 분포를 포함해 정의한다. 토큰 버킷·PID 컨트롤로 목표 RPS/TPS를 추적하고, 백프레셔와 실패 재시도 정책은 분리한다. 관측 구간 T에 커밋된 트랜잭션 수 N으로 TPS=N/T를 계산하되, 실패·드랍·재전송은 별도 집계한다.
재현 가능한 비교를 위해 고정 시드, 제네시스, 버전을 잠그고 컨테이너 기반으로 환경을 격리한다. 변경은 한 번에 하나씩 적용하며, 3회 이상 반복 측정해 통계적 유의성을 확보한다.
전파·합의·I/O를 분리해 병목을 찾는다
블록과 트랜잭션이 전체 피어에 도달하는 시간은 평균과 p99로 측정한다. netem/tc를 이용해 지연, 패킷 손실, 대역폭 제한을 주입하면 조건 변화에 대한 민감도를 확인할 수 있다. 피어 수, 고립 피어, 지리적 레이턴시가 합의 라운드에 미치는 영향도 함께 평가한다.
처리량 상한은 다음 근사치로 출발할 수 있다.
TPS_max ≈ block_gas_limit / avg_tx_gas / block_time
CPU의 검증·서명 처리, DB IOPS, 네트워크 대역폭 활용률을 동시에 프로파일링하면 병목 후보 사이의 상관관계를 볼 수 있다. 이후 노드 튜닝을 통한 수직 확장, 샤딩·롤업을 통한 수평 확장, 프루닝·스테이트 만기 같은 데이터 오프로드를 비교한다.
체인 유형에 따라 달라지는 관측 지점
Ethereum 계열에서는 가스 한도, 블록 시간, 피어 수, 가십 파라미터를 조정한 뒤 Caliper/web3 부하를 적용하고 p99 포함·최종성 지연을 분석한다. EIP-1559 변화에 따른 Mempool 대기와 스냅샷·프루닝 정책에 따른 DB 병목을 함께 확인한다. 프로토콜과 클라이언트 릴리스에 따라 파라미터의 의미가 바뀔 수 있으므로 최신 정보 확인이 필요하다.
Comet/Tendermint, Fabric 같은 BFT 합의 환경에서는 검증자 수를 4→16으로 바꾸고 메시지 크기를 조절하는 실험을 수행한 뒤 투표 라운드 타임아웃을 조정한다. 합의 단계별 타임아웃과 네트워크 RTT의 곱은 처리량 상한을 결정하며, 배치 크기와 동시성 윈도 역시 제어 대상이다.
Optimistic/ZK Rollup에서는 Sequencer TPS, L1 제출 빈도, 증명 지연을 분리해 측정한다. L1 가스 가격과 블록 스페이스 가용성은 L2의 유효 TPS와 지연에 직접 영향을 준다.
실험 중 발생하는 실패를 지표로 남긴다
입력은 워크로드 스펙, 체인 파라미터, 네트워크 조건이다. Warmup/Run/Cooldown을 포함한 실험 설계와 반복 횟수를 정한 뒤 부하를 인가하고 실시간으로 상태를 관찰한다. 이상 징후가 나타나면 조건부로 중단하며, 피어·블록 크기·DB 옵션을 교대로 바꾸어 병목 원인을 분리한다.
최종 결과에는 TPS, 지연 분포, 실패·드랍, CPU·메모리·IO·네트워크 사용률, 개선 권고안을 포함한다.
노드 큐 포화로 제출에 실패하면 백오프와 지수적 재시도를 적용하고 중복 제출 방지 키를 사용한다. 트랜잭션 일관성을 위해 넌스를 관리하며, 체인 재구성(Reorg) 구간은 제외하거나 확정성 기준을 합의한다. 컨트랙트 내부에서 경합하는 함수는 시나리오를 나누어 측정하고, 가스 한도를 넘는 Tx는 사전에 필터링한다.
합의 모델별 성능 특성
| 항목 | Nakamoto 계열(PoW/PoS) | BFT 계열(Tendermint/PBFT) | PoA/IBFT |
|---|---|---|---|
| 성능(처리량) | 중 | 중~고(검증자 수 적을 때 고) | 고 |
| 확장성 | 중(네트워크 전파 지배) | 낮음~중(노드 수 증가 시 O(n^2) 커뮤니케이션) | 중 |
| 일관성/최종성 | 확률적 최종성(확인 수 의존) | 즉시 최종성 | 즉시 최종성 |
| 안정성 | 높음(대규모 분산) | 중(네트워크 품질 민감) | 중 |
| 운영 편의 | 중(파라미터 복합) | 중(타임아웃 튜닝 필요) | 높음(권한형 노드 관리 용이) |
주: 구현체·버전에 따라 편차 존재, 최신 릴리스 노트 확인 필요.
TPS와 지연을 계산할 때의 기준
관측 구간이 T초이고 커밋된 Tx 수가 N이면 TPS는 N/T다. 확정성 기준 TPS는 확정이 끝난 Tx만 집계한다.
상한 근사치에서는 TPS_max ≈ block_gas_limit / avg_tx_gas / block_time을 사용한다. 예를 들어 block_gas_limit=30,000,000, avg_tx_gas=50,000, block_time=2s라면 30,000,000/50,000/2=300 TPS 근사치가 된다.
지연은 평균보다 p95와 p99를 보고한다. 롱테일의 개선 여부가 사용자 체감 품질을 좌우한다.
Ethereum 계열의 포함·최종성 지연 측정 코드
전제조건은 다음과 같다.
- Python 3.11, web3==6.x
- 실행 환경: 로컬 Devnet(geth --dev 또는 Anvil/Hardhat), 계정 프라이빗키 준비
- 체인 파라미터: 블록 타임 2s, 확정성 기준 12 블록 가정(최신 사양 확인 필요)
# pip install web3==6.11.3
import asyncio, time, statistics
from web3 import AsyncWeb3
from web3.providers.async_rpc import AsyncHTTPProvider
from eth_account import Account
RPC = "http://127.0.0.1:8545"
PK = "0x<PRIVATE_KEY>"
TO = "0x<RECEIVER_ADDRESS>"
TX_COUNT = 200
RATE = 50 # tx/sec 목표
async def main():
w3 = AsyncWeb3(AsyncHTTPProvider(RPC))
acct = Account.from_key(PK)
nonce = await w3.eth.get_transaction_count(acct.address)
gas_price = await w3.eth.gas_price
sent_times = {}
included_latencies, finalized_latencies = []
async def send_tx(i):
nonlocal nonce
tx = {
"to": TO,
"value": w3.to_wei(0, "ether"),
"nonce": nonce + i,
"gas": 21000,
"maxFeePerGas": gas_price*2,
"maxPriorityFeePerGas": gas_price//10,
"chainId": await w3.eth.chain_id
}
st = time.perf_counter()
signed = acct.sign_transaction(tx)
tx_hash = await w3.eth.send_raw_transaction(signed.rawTransaction)
sent_times[tx_hash.hex()] = st
return tx_hash
async def pace(i):
await asyncio.sleep(i / RATE)
return await send_tx(i)
# Open-loop pacing
tx_hashes = await asyncio.gather(*[pace(i) for i in range(TX_COUNT)])
# Inclusion wait
receipts = []
for h in tx_hashes:
r = await w3.eth.wait_for_transaction_receipt(h, timeout=120)
receipts.append(r)
inc = time.perf_counter() - sent_times[h.hex()]
included_latencies.append(inc)
# Finality wait (단순 확인수 기준)
CONF = 12
latest = await w3.eth.block_number
target = max(r.blockNumber for r in receipts) + CONF
while (await w3.eth.block_number) < target:
await asyncio.sleep(0.5)
for r in receipts:
fin = time.perf_counter() - sent_times[r.transactionHash.hex()]
finalized_latencies.append(fin)
def stats(xs):
return {
"count": len(xs),
"p50": round(statistics.median(xs), 3),
"p95": round(sorted(xs)[int(len(xs)*0.95)-1], 3),
"p99": round(sorted(xs)[int(len(xs)*0.99)-1], 3),
"avg": round(sum(xs)/len(xs), 3)
}
duration = max(sent_times.values()) - min(sent_times.values())
tps_submit = TX_COUNT / duration if duration > 0 else float("nan")
print("Submit rate TPS:", round(tps_submit, 2))
print("Included latency(s):", stats(included_latencies))
print("Finalized latency(s):", stats(finalized_latencies))
if __name__ == "__main__":
asyncio.run(main())
오픈루프인 위 코드와 동시성 워커를 유지하는 클로즈드루프를 모두 시험한다. 실패·드랍 Tx 로그는 분리하고, 넌스 충돌과 가스 부족 오류는 사전에 필터링한다.
성능을 높일 때 함께 감수하는 조건
피어 수를 줄이거나 리더를 고정하면 지연은 낮아질 수 있지만 검열과 장애에 대한 내성도 낮아진다. PoA/IBFT 같은 권한형 방식은 운영 편의성이 우수한 대신 신뢰 가정이 커진다.
프루닝과 스냅샷은 I/O 병목 완화에 도움이 되지만 역사 데이터 조회를 어렵게 만든다. 아카이브 노드를 분리하고 인덱싱 서비스를 도입하는 방식으로 절충할 수 있다.
블록 시간을 줄이면 지연은 감소하지만 포크율과 재구성 증가 가능성이 있다. 배치 크기를 키우면 처리량은 증가하나 꼬리 지연과 메모리 사용도 늘어난다.
피어 토폴로지와 가십 파라미터를 최적화하면 p99 블록 전파 지연을 3060% 줄일 수 있다. 블록 가스 한도, 배치 크기, DB 캐시 튜닝은 TPS를 1.53배 개선할 수 있으며, L2 롤업 도입 시 비용/처리량 효율은 10배 수준 향상이 가능하다(체인·시점별 상이, 최신 정보 확인 필요).
꼬리 지연을 줄이면 사용자 체감 품질이 좋아지고, 재현 가능한 벤치마크 체계는 릴리스 회귀 리스크를 낮춘다. 병목별 개선 우선순위가 드러나면 엔지니어링 자원도 더 효율적으로 배분할 수 있다.