본문으로 건너뛰기
0%

대기 중인 Ethereum 트랜잭션을 디버깅하는 방법

작성자: Alchemy Team

마지막 업데이트: 2021년 10월 20일6분 읽기

Ethereum 블록체인으로 트랜잭션을 보내면, 그것은 어디로 가는 걸까요? pending transaction이란 무엇이며, 채굴되기 전까지 무슨 일이 일어날까요? mempool이란 무엇일까요? 왜 어떤 트랜잭션은 성공하고 어떤 트랜잭션은 실패할까요?

이 글에서는 “send”를 누르는 순간부터 트랜잭션이 완전히 채굴되는 시점까지, Ethereum 네트워크에서 트랜잭션이 흘러가는 과정을 자세히 살펴봅니다. 이 과정에서 무엇이 잘못될 수 있는지, 그리고 Alchemy의 개발자 도구 모음이 이 과정을 디버깅하고 파악하는 데 어떻게 도움이 되는지 이야기하겠습니다.

이 가이드는 Ethereum을 기준으로 작성되었지만, 핵심 원리는 사실상 모든 블록체인에 그대로 적용됩니다!

Ethereum 트랜잭션이란 무엇인가?

Ethereum 트랜잭션은 가장 단순한 형태로 말하면, 블록체인의 영구 상태에 새로운 정보를 기록하기 위한 사용자의 요청입니다. 이 요청의 내용은 보통 다음 몇 가지 형태 중 하나를 취합니다:

  1. 사용자의 공개 계정에서 다른 대상으로 가치를 단순 전송하는 것 (예: 가맹점에 ETH를 보내는 경우)
  2. 다른 제3자가 접근할 수 있는 새로운 스마트 컨트랙트를 퍼블릭 블록체인에 기록하는 것 (예: 새로운 복권 스마트 컨트랙트를 시작하는 경우)
  3. 기존 스마트 컨트랙트에 정보를 보내 해당 컨트랙트와 상호작용하는 것 (예: 복권 스마트 컨트랙트에 이름과 자금을 입력하는 경우)

mempool이란 무엇인가?

Ethereum의 트랜잭션 흐름을 이해하기 전에, 먼저 mempool이 무엇인지 알아야 합니다! mempool은 Ethereum 노드 내에서 미확인 트랜잭션이 대기하는 공간으로, 스테이징 영역 역할을 하도록 특별히 구성되어 있습니다. 사용하는 클라이언트에 따라 TX-POOL 또는 TX-QUEUE라고 불리기도 합니다.

노드로 전송된 트랜잭션은 먼저 mempool에 도착하며, 네트워크에 의해 완전히 확인되기 전까지 그곳에 머무릅니다. mempool은 다음과 같은 몇 가지 핵심 단계를 처리합니다:

  1. 트랜잭션이 채굴자에게 제출되었을 때 성공적으로 처리될 수 있는지 확인하기 위해 일련의 유효성 검사를 실행합니다. 노드가 수행할 수 있는 검증에는 다음과 같은 것들이 있습니다: gas 비용을 감당할 만한 자금이 있는가? 트랜잭션 서명이 유효한가? 해당 발신 주소의 nonce가 순서상 다음 값인가?
  2. gas 가격을 기준으로 처리할 트랜잭션 목록의 순서를 정합니다. gas 가격이 높을수록 채굴자가 해당 트랜잭션을 우선적으로 처리할 가능성이 높아집니다.
  3. pending 상태의 트랜잭션을 피어 노드의 mempool과 공유하고, 이는 다시 다른 mempool로 계속 전파되어 네트워크 전체가 pending 트랜잭션 목록을 볼 수 있게 됩니다. 블록이 채굴되면, 네트워크 전체에서 gas 가격이 가장 높은 트랜잭션들이 확정됩니다.

Ethereum 트랜잭션 흐름은 어떻게 이루어지는가?

지금까지 mempool에 대해 다루었으니, 이제 사용자가 트랜잭션을 보내는 순간부터 이 트랜잭션이 블록체인에 영구적으로 저장되기까지 어떤 단계를 거치는지 살펴보겠습니다.

  1. 사용자가 새로운 트랜잭션을 생성하고, 자신의 private key로 서명한 뒤, 보통 Alchemy의 Node API와 같은 서비스를 통해 노출되는 eth_sendTransaction 또는 eth_sendRawTransaction 메서드를 호출하여 블록체인의 한 노드로 전송합니다.
  2. 트랜잭션은 해당 노드의 mempool로 전송됩니다.
  3. mempool은 일련의 유효성 검사를 실행합니다. 트랜잭션이 이 검증을 통과하면 pending 상태가 됩니다.
  4. 노드는 트랜잭션을 블록체인의 다른 노드들에 전파하며, 이 트랜잭션은 각 노드의 mempool에도 반영됩니다.
  5. 블록체인의 어느 노드가 새로운 블록을 채굴하면, gas 가격이 가장 높은 약 200개의 pending 트랜잭션이 다음 블록에 포함됩니다. 이 트랜잭션들은 mempool에서 제거되고, 새 블록과 mempool 상태가 네트워크 전체에 전파됩니다.
  6. 이후 5~7개의 블록이 추가로 확정되면, 블록체인이 다른 fork (다른 확정 트랜잭션 집합을 가진)를 따르도록 재구성될 가능성은 극히 낮아집니다. 이 시점에서는 해당 트랜잭션이 블록체인에 영구적으로 기록되었다고 안전하게 간주할 수 있습니다.
서명부터 블록 확정까지 Ethereum 트랜잭션 흐름을 나타낸 다이어그램
Ethereum 트랜잭션 흐름

pending 상태의 Ethereum 트랜잭션에서 무엇이 잘못될 수 있는가?

1. mempool이 가득 찼을 수 있다

간단한 것부터 시작해봅시다. mempool의 크기에는 제한이 있습니다 (Alchemy와 같은 도구를 사용하지 않는 한!). 이는 노드 전체 단위로도, 노드 내 주소별 단위로도 적용됩니다. Geth의 경우 보통 4096개의 pending 트랜잭션이 한도이며, Geth는 오래된 pending 트랜잭션을 최신 트랜잭션을 위해 제거합니다.

2. 파라미터가 잘못되었을 수 있다

트랜잭션을 생성할 때는 다음과 같은 다양한 관련 파라미터를 포함해야 합니다:

  • 발신 주소와 수신 주소는 무엇인가?
  • 전송할 금액은 얼마인가?
  • 트랜잭션에 사용할 의향이 있는 gas는 얼마인가?
  • 내 트랜잭션의 현재 nonce는 무엇이어야 하는가?

이 값들을 입력하는 과정에서 실수가 있었다면, 노드는 보통 문제를 설명하는 에러 코드를 반환합니다. 에러 메시지를 이해할 수 없거나 검색으로도 답을 찾을 수 없다면 Alchemy 지원 센터를 방문하세요.

3. gas 가격이 너무 낮을 수 있다

어떤 트랜잭션을 우선 처리할지 결정하기 위해, Ethereum 트랜잭션은 gas 가격을 함께 제출해야 합니다. 일반적인 경매와 마찬가지로, gas 가격이 높을수록 다음 블록에 포함될 가능성이 높아지고, gas 가격이 너무 낮으면 블록체인에 영원히 기록되지 못할 수도 있습니다.

gas 가격은 하루 중에도 수요에 따라 빠르고 예측 불가능하게 변동하기 때문에, 이 필드를 제대로 설정하는 것이 매우 중요합니다. 몇 가지 선택지가 있습니다:

  • 단일 트랜잭션을 수동으로 보내는 경우, ETH Gas Station 웹사이트를 방문해 최신 gas 가격을 확인하고 그에 맞게 설정할 수 있습니다.
  • Alchemy와 같은 노드 프로바이더로 요청을 보내는 경우, Ethereum JSON-RPC 스펙에는 eth_estimateGas라는 엔드포인트가 있어 트랜잭션이 채굴되는 데 필요한 gas의 추정치를 제공합니다! 이를 활용해 gas 가격 설정을 프로그래밍 방식으로 자동화할 수 있습니다.
  • gas 가격이 특정 값 이상으로 오르거나 이하로 떨어졌을 때 푸시 알림을 받고 싶다면, 이런 상황을 정확히 알려주는 Alchemy Notify의 Gas Price Notifications라는 도구를 제공합니다! 이는 webhook이기 때문에, gas 가격이 낮을 때 자동으로 트랜잭션을 보내도록 코드에 통합하기가 매우 간단합니다.
Alchemy Dashboard Demo
Free video demo

Alchemy 대시보드 작동 모습 보기

30분 가이드 투어: 대시보드의 모든 도구를 실시간으로 시연합니다.

Watch the demo

4. nonce가 잘못되었을 수 있다

아, 모두의 마음속에 자리 잡고 있는 궁금증 - 도대체 nonce가 뭐고 왜 필요한 걸까요?? 당연히 물어볼 만한 질문이고, 물어봐 주셔서 기쁩니다.

간단히 말해, nonce는 특정 주소에서 보낸 트랜잭션의 개수입니다. 다섯 개의 트랜잭션 (nonce 0-4)을 성공적으로 확정했다면, 다음 pending 트랜잭션의 nonce는 5가 됩니다.

nonce는 몇 가지 규칙을 따릅니다:

  • nonce는 반드시 순서대로 발생해야 합니다. nonce 4인 트랜잭션은 nonce 5인 트랜잭션보다 반드시 먼저 처리됩니다.
  • nonce는 중복되거나 건너뛸 수 없습니다 - 성공한 트랜잭션마다 정확히 하나의 nonce가 대응됩니다. nonce 5인 트랜잭션이 없다면 nonce 6인 트랜잭션을 제출할 수 없습니다. 마찬가지로 nonce 5인 트랜잭션 두 개를 제출할 수도 없습니다 - 그중 하나만 처리됩니다.

왜 nonce가 필요할까요? nonce는 특정 주소에서 보낸 트랜잭션들이 보낸 순서대로 처리되도록 보장하고, 이중 지불(double-spend) 문제로부터 트랜잭션을 보호하기 위해 암호학적 관점에서 필요합니다.

실제로 nonce는 트랜잭션을 생성할 때 설정해야 하는 단순한 파라미터일 뿐입니다. 이를 통해 트랜잭션의 순서를 세밀하게 수동으로 제어할 수 있습니다.

실제 사례를 들자면, 마켓플레이스에서 NFT를 구매하고, 그것을 찾는 데 도움을 준 Bob에게 소액의 “수고비”를 보내고 싶다고 해봅시다. 이 경우, NFT 구매에 성공했을 때만 Bob에게 돈을 지불하고 싶을 것입니다. nonce가 없다면 두 트랜잭션을 모두 제출하면서 그것들이 특정 순서대로 처리되도록 보장할 방법이 없습니다. nonce를 사용하면 하나의 트랜잭션에는 nonce N을, 다른 하나에는 nonce N + 1을 지정하기만 하면 됩니다!

하지만 이런 세밀한 제어는 매번 올바른 nonce로 트랜잭션을 제출해야 한다는 것을 의미합니다! 트랜잭션이 막혀 있다면, 위에서 설명한 규칙에 따라 nonce가 제대로 설정되어 있는지 확인해야 합니다.

5. 블록이 fork될 수 있다

이건 정말 마음에 드실 겁니다: 트랜잭션이 성공적으로 채굴되었더라도, 여전히 안심할 수 없습니다 😡 .

블록체인은 탈중앙화되어 있기 때문에, 네트워크 내의 서로 다른 노드 집합이 네트워크에 대해 서로 다른 뷰를 가질 수 있습니다. 특히 두 명의 채굴자가 거의 동시에 새로운 블록을 채굴하는 경우가 가끔 발생하며, 피어 노드들은 비슷한 비율로 두 개의 새로운 체인에 각각 올라타게 됩니다. 이 경우 두 체인은 병렬로 성장하지만, 결국 둘 중 하나가 아주 조금 더 많은 합의를 얻게 됩니다!

네트워크 전체가 그중 한 체인으로 전환하고 다른 체인을 버리면, 이전 체인에서 이미 “채굴된” 트랜잭션들은 fork되어 무효가 됩니다. 이렇게 fork된 블록을 “uncle block”이라고도 부릅니다.

즉, 트랜잭션을 채굴한 이후에도 블록 fork에 의해 여전히 무효화될 수 있다는 뜻입니다! 여기서 Etherscan의 fork된 블록 이력을 확인할 수 있습니다. 다행히 Ethereum mainnet에서는 이런 일이 그리 흔치 않고 보통 5블록 이내의 깊이에서 발생하지만, 바로 이 때문에 DeFi 거래 프로토콜에서는 최소 5~7개의 블록 확정이 이루어지기 전까지는 트랜잭션이 “완전히” 확정되었다고 보지 않습니다.

mempool과 Ethereum pending 트랜잭션을 관리하기 위해 어떤 도구를 사용할 수 있는가?

Alchemy mempool watcher

40분 전에 노드의 mempool로 트랜잭션을 보냈는데, 아직 블록체인에서 확정된 것을 확인하지 못했다고 해봅시다. 현재 상태, 보낼 때 설정한 gas 가격, 그리고 이중 확인을 위한 nonce에 대한 정보를 알고 싶습니다. 어떻게 해야 할까요?

mempool 트랜잭션의 상태를 확인하는 일은 예전에도 (그리고 지금도) 골치 아픈 일이었습니다. mempool 상태로 접근할 수 있는 유일한 인터페이스가 Ethereum JSON-RPC API뿐이기 때문에, 개발자들은 트랜잭션을 보낸 여러 노드에 각각 쿼리를 보내고, 수많은 로그 페이지를 병합하고 뒤지며, 단 하나의 조회를 위해 mempool 전체 상태를 수작업으로 재구성하는 데 몇 시간을 쏟아야 했습니다.

바쁜 mempool에 대한 일반적인 호출은 이런 모습입니다:

멤풀 상태 요청에 대한 원시 JSON 응답, 조밀하고 읽기 어려움
이 복잡한 내용을 잘 읽어보시기 바랍니다.

더 나쁜 것은, 개발자들이 확장을 위해 여러 노드에 요청을 보내기 시작하면 심각한 일관성 문제가 발생한다는 점입니다 - 트랜잭션은 단일 노드에서 시작되므로, 특정 트랜잭션에 대한 요청은 그것과 상호작용할 때마다 항상 같은 노드로 sticky routing되어야 합니다.

이러한 문제에 대응하여, 저희는 이 복잡함을 상당 부분 단순화하는 도구인 Mempool Watcher를 만들었습니다. 먼저, 저희가 모든 노드 라우팅을 처리하기 때문에, 수십 개의 노드를 규모에 맞게 활용하고 있더라도 mempool은 항상 하나의 단일 entity처럼 보이며, mempool 요청은 저희 인프라 내에서 올바른 노드로 적절히 라우팅됩니다.

둘째로, 트랜잭션 상태를 실시간으로 볼 수 있는 아주 유용한 도구들을 제공합니다. 트랜잭션은 mined, pending, dropped 중 하나로 표시됩니다. 각 트랜잭션 기록에는 해당 트랜잭션이 pending 상태로 머문 시간, 필요한 gas 양, 그리고 추가 세부 정보에 대한 접근이 포함됩니다.

저희 도구를 사용하면 멤풀 화면이 이렇게 보입니다!
저희 도구를 사용하면 멤풀 화면이 이렇게 보입니다!

Alchemy explorer

스크립트를 통해 노드에 동시에 20개의 서로 다른 트랜잭션을 보냈는데, 그중 일부는 노드에 도달조차 하지 못하고 실패하는 것을 발견했다고 해봅시다. 실패한 응답을 추적하고 패턴을 찾아 원인을 파악하려면 어떻게 해야 할까요?

위와 마찬가지로, 개발자는 보통 패턴을 파악하기 위해 수많은 로그 페이지를 뒤져야 했습니다. 이에 대응해, 저희는 API를 통해 전송된 JSON-RPC 요청의 상태를 추적할 수 있는 request/response explorer 도구를 만들었습니다!

과거 JSON-RPC 요청 및 응답 목록을 보여주는 Alchemy Explorer
Alchemy Explorer

저희 Alchemy Explorer를 사용하면 1초 전부터 최대 7일 전까지 저희 인프라를 통해 전송된 과거의 요청과 응답을 검색할 수 있습니다! 더 이상 로그를 뒤질 필요 없이, 최신 기술을 바로 활용할 수 있습니다.

이 요청들에 대해 메서드 종류, HTTP 응답, 노드별 오류 등 다양한 파라미터로 쿼리를 필터링할 수 있습니다! 타임스탬프, 요청 소요 시간 등 여러 기준으로 요청을 확인할 수 있습니다.

왜 트랜잭션 관리를 위해 Alchemy를 사용해야 하는가?

Alchemy는 노드 프로바이더입니다. 즉, Ethereum 블록체인 (그 외 몇몇 블록체인도 포함해!)으로 요청을 주고받는 데 관련된 모든 인프라를 저희가 관리한다는 뜻입니다. 노드 프로바이더가 왜 필요한지에 대한 정보는 여기에서 확인하실 수 있습니다.

일단 저희 시스템을 통해 요청을 보내기 시작하면, 앞서 다룬 pending 트랜잭션 관련 이점들 - 확장 가능한 mempool, 대시보드 도구, gas 가격 webhook - 을 모두 누릴 수 있습니다.

그뿐만 아니라, 다음도 제공합니다:

  • 블록체인이 안고 있는 확장성 및 일관성 문제를 해결하는 자체 인프라를 기반으로 한 Alchemy의 Node API 접근 권한.
  • 위에서 다룬 것과 같은 요청 탐색 도구를 제공하여 애플리케이션을 구축하고 모니터링하는 데 도움을 주는 Dashboard 접근 권한.
  • 블록체인에서 발생하는 트랜잭션 등의 이벤트에 대해 푸시 알림 (webhook)을 제공하는 도구인 Alchemy Notify 접근 권한.
  • 원래라면 연산 비용이 많이 들거나 불가능한 블록체인 요청을 가능하게 해주는 Enhanced API 접근 권한.
  • 그 밖에도 Flow, Crypto.org, 그리고 Polygon, Optimism, Arbitrum 같은 L2를 포함한 다양한 체인에서 이러한 기능들에 접근할 수 있습니다!

Alchemy 시작하기

Alchemy의 Node API와 개발자 도구를 사용하는 것은 정말 간단합니다 - 사실 단 한 줄의 코드면 충분합니다! web3.js나 ethers.js를 사용해 왔다면, Alchemy 계정을 무료로 생성하고 API 키를 발급받은 뒤, 인스턴스 생성 부분을 다음과 같이 바꾸기만 하면 됩니다:

전체 튜토리얼을 원하신다면 Getting Started with Alchemy 가이드를 읽어보세요. 추가 도움이 필요하시면 Alchemy 지원 센터를 방문해 주세요.

Alchemy 뉴스레터

출시 소식을 가장 먼저 받아보세요

뉴스레터 구독하기

Alchemy의 최신 제품 업데이트와 리소스 받기

A
O
D
+
구독자 80,000명 이상

이메일 주소를 입력하면 마케팅 커뮤니케이션 및 제품 업데이트 수신에 동의하게 됩니다. Alchemy는 저희 개인정보 처리방침에 따라 수집한 정보를 처리합니다. 언제든지 구독을 취소할 수 있습니다.