본문으로 건너뛰기
0%

데이터 정확성: Web3의 잘 알려지지 않은 고질적인 문제

작성자: Alchemy Team

마지막 업데이트: 2022년 7월 14일8분 읽기

잘 알려진 한 NFT 팀은 사용자들에게 서로 모순되는 정보를 보여준 탓에 수만 명의 사용자를 잃었다 (위 예시 참고).

가장 큰 DeFi 프로토콜 중 하나는 사용자에게 프론트엔드 오류를 일으키는 버그를 처리하는 과정에서 200만 달러를 잃었다. 근본 원인을 찾아내지 못해, 문제는 몇 주 동안 해결되지 않았다.

이 두 상황은 동일한 문제, 즉 노드 인프라의 정확성 부족에서 비롯된다. 이는 Web3에서 만연한 문제다.

엔지니어, 창업자, 프로덕트 매니저, 심지어 사용자라 하더라도, 노드 정확성이 아직 관심사가 아니었다면 앱을 성공시키기 위해 최우선 순위로 삼아야 한다.

배경 설명

블록체인은 P2P 네트워크에서 서로 통신하는 노드들에 의해 운영된다. 바로 이 구조적 요소가 탈중앙화를 가능하게 하며, 이는 web3의 핵심 가치 제안 중 하나다: 중앙 중개자에 의존하는 대신, 수천 개의 노드가 서로 신뢰 없이 정보를 전파하며 트랜잭션을 기록한다.

사용자에게 정확하고 일관된 결과를 제공하려면, 노드 네트워크가 블록체인의 최신 상태에 대해 합의해야 한다. 이는 P2P 네트워크에서 매우 까다로운 일인데, 정보가 각 노드에 동시에 도달하지 않기 때문이다.

즉, 사용자가 노드에 의존해 데이터를 제공받는 dApp과 상호작용할 때:

  • 노드들이 항상 같은 데이터를 제공하는 것은 아니다 ➡️
  • 사용자는 항상 기대한 결과를 받는 것은 아니다
NFT가 지갑에 제때 표시되지 않는 문제
NFT가 지갑에 제때 표시되지 않는 문제

사용자가 납득할 수 없는 예상 밖의 정보나 서로 모순되는 정보를 받게 되는 경우, 대부분은 사용 중인 노드들 사이에 정확성이 부족하기 때문이다.

Alchemy는 정확성을 사용자가 dApp과 상호작용할 때 정확하고 일관된 데이터를 돌려받는 상태로 정의한다.

이 글에서는 다음을 설명한다:

  • 정확성이 왜 web3 특유의 문제인지
  • 단일 노드로 정확성 문제를 해결하는 것의 한계
  • 로드 밸런서로 정확성 문제를 해결하는 것의 한계
  • 정확성 부족이 앱 전반에 어떻게 문제를 일으키는지
  • Alchemy의 Cortex 엔진이 블록체인 정확성 문제를 어떻게 해결하는지

정확성은 사용자가 dApp과 상호작용할 때 정확하고 일관된 데이터를 돌려받는 상태에서 존재한다

web2에서는 [중앙화된 시스템 덕분에 정확성이 쉽게 해결되는 문제다](https://ethereum.org/en/developers/docs/web2-vs-web3/#:~:text=Web2 refers to the version,that run on the blockchain), 정보가 단 하나의 소스에서만 나올 수 있기 때문이다. 하지만 web3의 분산 시스템은 다음과 같은 다양하고 복잡한 문제들을 야기한다:

  • 복잡한 구현
  • 네트워크에서 가장 먼 참여자에게까지 정보가 전달되도록 보장하는 어려움 (네트워크상 더 멀리 있는 노드에 정보가 도달하는 데 실제로 더 오랜 시간이 걸린다)
  • 네트워크 조율의 어려움

노드 그룹 사이에 정확성 부족을 초래할 수 있는 이 모든 문제들은 다음으로 이어질 수 있다:

  • 망가진 경험 제공
  • 고객 이탈
  • 문제를 사후적으로 고치느라 시간과 비용 낭비

"CryptoKitties에서 상상할 수 있는 모든 상태 문제가 일어났습니다. 노드들이 동기화되지 않으면 사용자 경험과 dApp 전체가 엉망이 됐죠." - Eric Lin, Dapper

단일 노드를 운영할 때의 문제점

데이터 정확성 문제가 여러 노드 간 통신에서 비롯된다면, 직접 단일 노드를 운영하기로 결정할 수도 있다.

직접 단일 노드를 운영하고 있고, 한 사용자가 dApp에 요청을 보낸다고 가정해보자:

  • 사용자가 최신 블록을 요청한다
  • 노드는 최신 블록이 4라고 알려준다
단일 노드로 실행되는 dApp에 사용자가 최신 블록을 요청하는 다이어그램
사용자가 dApp을 호출함

✅ 문제없이 동작한다!

하지만 함정이 있다.

이는 어느 시점까지만 통한다.

단일 노드로 트래픽을 처리하면 앱의 확장성과 안정성이 크게 제한된다:

  • 확장성: 현재 dApp에 100명의 사용자가 있는데 사용량이 10배로 늘어난다면, 노드 하나로는 늘어난 요청 부하를 효과적으로 처리할 수 없다
  • 안정성: 노드 하나에 의존한다면, 그 노드가 다운되었을 때 dApp도 함께 다운된다. 그리고 노드는 원래 신뢰성이 떨어지는 것으로 악명이 높기 때문에, 단 하나만 쓰면 필요한 만큼의 가동 시간을 확보할 수 없다 (우리가 측정한 바로는 단일 노드의 가동 시간이 일부 경우 72%까지 낮게 나타났다).

팀이 노드 유지보수에 쓰는 시간만큼, 제품과 경험을 만드는 데 쓸 수 있는 시간이 줄어든다.

"Alchemy와 함께 일하면서 저희는 항시 인프라 유지보수에 매달려야 했을 풀타임 엔지니어 세 명분의 공수를 절약할 수 있었습니다." - Evgeny Yurtaev, Zerion CEO 겸 공동 창업자

자, 단일 노드로는 사업 요구를 충족하기 부족하다는 걸 알게 됐다. 그럼 다음에 무엇을 할 수 있을까?‍

로드 밸런서 사용의 문제점

여러 노드에 걸쳐 트래픽을 관리하는 로드 밸런서를 사용하는 인프라 제공업체를 시도해볼 수도 있다. 이는 web3에서 매우 흔한 인프라 설계다.

로드 밸런싱은 원래 web2에서 사용되던 수평 확장 메커니즘이다. 로드 밸런싱은 마트에서 가장 짧은 줄을 고르는 것과 비슷하다 - 로드 밸런서는 dApp의 트래픽을 가장 짧은 줄을 선 노드로 보낸다.‍

아래 예시를 보자.

한 사용자가 dApp에 요청을 보낸다:

  • 최신 블록을 요청한다
  • Node A를 통해, dApp은 최신 블록이 2라고 알려준다

그런 다음 사용자가 확인을 위해 다시 요청한다:

  • 이번에는 쿼리가 Node B로 라우팅된다
  • Node B를 통해, dApp은 최신 블록이 4라고 알려준다

시스템이 여전히 각 요청을 단일 노드를 통해 라우팅하고 있고, 어느 시점에서든 그 노드가 최신 정보를 갖고 있지 않을 수 있기 때문에, 결과는 종종 부정확하다. 사용자는 납득할 수 없는 서로 모순된 결과를 받게 된다.

로드 밸런싱은 단일 노드보다 더 많은 확장성과 안정성을 제공하지만, 그 대가로 정확성을 잃는다.

트래픽이 로드 밸런서를 통해 라우팅될 때, 노드들은 다음에 대해 서로 다른 정보를 가질 수 있다:

  • 최신 블록
  • 가장 최근 트랜잭션
  • 대기 중인 트랜잭션

이러한 문제들은 다음을 의미할 수 있다:

아직도 이게 큰 문제라는 게 와닿지 않는다면, 계속 읽어보자.

정확성 부족이 어떻게 중대한 문제를 일으키는가

Isaac이 DAO에 가입하고 싶어하고, 그러려면 DAO의 토큰을 구매해야 한다고 가정해보자.

  • Isaac이 탈중앙화 거래소(DEX)에 묻는다: "DAO 토큰 아직 살 수 있어?"
  • DEX의 인프라 제공업체가 Isaac의 요청을 Node A로 라우팅한다.
  • Node A를 통해, DEX가 그에게 답한다: "네, 토큰이 아직 남아 있습니다."

✅ 토큰을 구매할 수 있다!

Isaac이 구매를 시도한다.

  • DEX의 인프라 제공업체가 Isaac의 요청을 Node B로 라우팅한다.
  • Node B를 통해, DEX가 그에게 답한다: "트랜잭션이 실패했습니다."

DEX가 노드 간 로드 밸런싱을 하는 인프라 제공업체를 사용하고 있었기 때문에 (web3에서 매우 흔한 확장 메커니즘), Isaac이 토큰이 아직 있는지 확인했을 때 Node A는 이 경우 오래된 정보를 반환했다.

여기서 핵심 요점이 드러난다: 로드 밸런서를 사용할 때 정보가 항상 나오는 곳인 개별 노드에서 특정 시점에 오는 정보는 신뢰할 수 없다.

그 노드는 최신 정보를 갖고 있지 않을 수 있으며, 만약 그 노드가 요청에 응답한다면 트랜잭션(또는 이후의 트랜잭션들)이 실패하거나 예상치 못한 동작을 보일 가능성이 높다.

Build vs. Buy ebook cover
무료 가이드

Build vs. Buy: 블록체인 인프라

인프라 팀을 채용하기 전에 읽어보세요: 자체 구축 시 프로덕션 요청을 단 하나도 처리하기 전에 연간 $850K~$1M 이상이 들 수 있습니다. 전체 비용 분석을 확인하세요.

가이드 다운로드

정확성 문제는 다양한 실패 상태를 초래한다

Isaac에게 일어난 일은 노드 정확성 부족으로 인한 여러 실패 상태 중 하나일 뿐이다.

몇 가지 다른 잠재적 실패 상태를 더 살펴보자:

  1. 스마트 컨트랙트 실행이 하나의 사실적 결과만 있어야 하는데도 서로 모순되는 답을 반환하는 경우. 예를 들어:
  • 사용자가 묻는다: "이 Bored Ape는 누구 소유야?"
  • API가 답한다: "Alice"
  • 그런 다음 사용자가 묻는다: "Alice가 소유한 ape들을 알려줘?"
  • API가 답한다: "Alice는 아무것도 소유하고 있지 않습니다"‍

왜 이런 일이 일어났을까? 로드 밸런서에 의존하는 인프라에서는 스마트 컨트랙트의 상태, 즉 컨트랙트를 실행했을 때의 결과가 어떤 노드가 요청을 처리하느냐에 따라 달라진다.

  1. dApp이 잘못된 "nonce" (특정 지갑 주소에서 나오는 각 개별 트랜잭션의 고유 식별자)를 반환하여, 이후 트랜잭션이 실패하는 경우. 예를 들어:
  • 사용자가 nonce 100으로 트랜잭션 1을 완료한다
  • 사용자가 묻는다: "다음 nonce는 뭐야?"
  • API가 답한다: 100 (nonce 100은 이미 완료되었으므로 이는 있을 수 없는 일이다)
  • 다음 트랜잭션은 자동으로 거부된다

_왜 이런 일이 일어났을까? 부정확한 인프라에서는 _대기 중인 트랜잭션이 단 하나의 노드에만 남아 있을 수 있어서, 그 대기 중인 트랜잭션들의 상태나 이를 보낸 지갑에 대한 정보를 요청하면 누락되거나 오해의 소지가 있는 데이터가 반환되는 경우가 매우 흔하다.

이러한 실패 상태는 교묘하고, 납득하기 불가능하며, 앱의 상태에 심각한 영향을 미친다

일어날 수 있는 몇 가지 일들:

부정확한 데이터를 수집하여 데이터베이스가 오염될 수 있으며, 이를 고치는 데 시간과 노력이 필요하다.

Origin의 사례를 보자. 그들의 첫 번째 인프라 제공업체에서는 RPC 오류와 디버깅이 흔하게 발생했고, 오류를 디버깅하는 일은 팀에게 시간이 많이 드는 작업이었다.

그들은 한 노드가 요청에 응답했지만, 그 노드가 다른 요청에 응답한 노드보다 몇 블록 뒤처져 있었다는 것을 발견했다.

이러한 상태 문제는 문제 해결이 사실상 불가능했고, 근본 원인을 찾아냈을 때는 이미 시스템 전체가 오염된 상태였다.

이런 문제들에는 오류 메시지나 실패 코드가 존재하지 않기 때문에, a) 코드에서 이를 사전에 대비할 수 없고 b) 문제가 발생하면 몇 시간씩 디버깅에 매달리게 된다. 이는 사용자에게도 똑같이 혼란스러운 경험이 된다:

Bakery swap에서 NFT 전송 중 오류 발생
Bakery swap에서 NFT 전송 중 오류 발생

**사용자는 오래된 데이터를 기반으로 트랜잭션을 보내게 되어 실패가 확정되며, 그 결과 가스비를 잃게 될 수 있다:**‍

지갑에서 NFT가 사라졌다는 사용자 신고
사라진 NFT

사용자는 dApp에서 트랜잭션이 성공했는지 실패했는지를 연이어 다르게 보여주는 모순된 UI를 보게 될 수 있다. 사용자는 이 실패를 dApp의 프론트엔드 경험 탓으로 돌릴 것이다:

4시간이 지나도 사용자 지갑에 NFT가 표시되지 않음
4시간이 지나도 사용자 지갑에 NFT가 표시되지 않음

사용자는 트랜잭션이 채굴되지 않았다고 생각해 다시 시도함으로써 과다 지불하게 될 수 있다; 실제로는 원래 트랜잭션이 처리되었지만 정확하게 반영되지 않았을 뿐이다:

실패한 트랜잭션에 대해 가스비를 두 번 지불한 사용자
실패한 트랜잭션에 대해 가스비를 두 번 지불한 사용자

정확성을 염두에 둔 설계

아직 명확하지 않았다면 말하자면, 블록체인 네트워크에서 부정확한 인프라는 dApp과 사용자에게 매우 부정적인 영향을 미칠 수 있다.

다음과 같은 인프라 제공업체와 함께 일해야 한다:

  • 정확성을 근본적인 우선순위로 여기는 제공업체
  • dApp이 확장될 때 정확성을 유지하기 위해 로드 밸런싱과는 다른, 지속 가능한 시스템을 갖춘 제공업체

노드 제공업체 벤치마킹

잘 알려진 몇몇 노드 인프라 제공업체들의 정확성을 벤치마킹한 데이터를 정리했다. 이 도구를 사용해 직접 정확성을 벤치마킹해보기 바란다.

정확성은 제공업체를 평가하는 한 요소일 뿐이다. Alchemy의 RPC 제공업체 벤치마크에서 현재 지연 시간, 성공률, 실패한 요청 비율도 비교할 수 있다.

테스트에서는 각 제공업체에서 최신 블록 번호를 가져오기 위해 24시간 동안 JSON RPC 메서드 _eth_blockNumber_를 총 약 107만 2천 회 호출했다. 이는 데이터 부정확성을 벤치마킹하는 하나의 간단한 예시일 뿐이다. 더 자주, 더 치명적으로 실패하는 다른 방식들도 많다.

24시간 동안 노드 인프라 제공업체별 데이터 정확도를 비교한 차트
노드 제공업체 벤치마킹

참고 샘플 대시보드 스냅샷에서는 하루 동안의 데이터 정확성을 쿼리하고 기록했다.

*전체 방법론 세부사항은 부록 참고.

정확한 데이터를 얻으려면 어떻게 해야 할까?

"Alchemy는 이전에 발생했던 일관성 문제를 해결하여, 사용자 불만의 98%를 제거하고 Augur의 사용자 경험과 채택률을 크게 개선했습니다." - Augur CTO Alex Chapman

앱과 고객을 위한 정확성을 보장하기 위해, Alchemy는 수십만 시간의 엔지니어링 공수를 투입하고 수백 가지의 독자적인 혁신을 개발해 Alchemy의 Cortex 엔진을 구축했다. Cortex 엔진은 멀티 노드 인프라의 확장성과 안정성 이점을 유지하면서도 일관된 데이터 정확성을 보장한다.

Cortex는 단순히 여러 노드를 연결해 놓은 것 이상이다 - 사실 그건 Cortex 엔진이 하는 일의 극히 일부에 불과하다. Cortex는 커스텀 설계된, 확장 가능하고 분산된 시스템들을 결합하여 우리의 API가 본질적으로 단일 노드처럼 동작하도록 만들며, 이를 통해 지금까지 다룬 모든 정확성 문제를 해결한다.

이것이 어떻게 동작할까?

우리는 Vox Nodi (노드들의 목소리)라는 명시적 일관성 레이어를 구축했다. Vox Nodi의 역할은 우리가 처리를 돕는 모든 블록체인 요청이 일관된 결과를 반환하도록 보장하는 것이다.

이는 본질적으로 우리 인프라 전반에서 합의 알고리즘을 실행하는 방식으로 동작하며, 인프라의 각 구성 요소가 블록체인의 올바른 상태에 대해 투표할 수 있다.

쿼리를 올바르게 라우팅하고 조정함으로써, 이 시스템은 특정 시점에 여러 노드가 트랜잭션 데이터에 대해 서로 다른 시각을 갖고 있더라도 결과는 항상 일관되게 정확하도록 보장한다.

간단히 말해, Vox Nodi는 우리 API에 대한 모든 요청이 빠르고, 안정적으로, 100% 정확한 데이터와 함께 반환되도록 보장한다.

그리고 Cortex는 여전히 개발자가 무한히, 안정적으로 확장할 수 있게 해준다. 개별 노드가 아니라 완전한 분산 블록체인 엔진이 각 요청에 응답하기 때문이다.

한마디로, 이는 로드 밸런서가 아니다.

시사점 및 결론

dApp을 블록체인에 연결하는 방식을 선택할 때 고려해야 할 다양한 측면이 있다: 제공업체의 정확성 제공 능력이 목록의 최우선순위가 되어야 한다.

Alchemy에게 정확성은 최우선 과제다. 오늘 Alchemy에서 무료로 시작해보자.

부록

벤치마킹 방법론

정확성 벤치마킹을 고민하면서, 우리는 기본 원리에서 출발해 가장 기초적인 Ethereum RPC 호출 중 하나인 eth_blockNumber를 테스트했다.

참고로, eth_blockNumber는 Ethereum 네트워크의 최신 블록 번호를 반환하며, 탈중앙화 네트워크에서는 가장 높은 블록 번호를 가진 블록이 가장 최근의 트랜잭션을 담고 있다.

이런 이유로, 정상적인 네트워크 상황에서는 단일 노드/노드 제공업체에서 eth_blockNumber를 호출할 경우 오직 증가하는 값의 블록 번호만 반환되어야 한다. 증가하는 데이터에서 불일치가 발생한다면 이는 되돌림(reversion)을 나타내거나, 더 빈번하게 발생할 경우 제공업체의 데이터 부정확성 가능성을 나타낸다.

이는 새로운 최장 체인이 노드의 기존 데이터를 대체하는 '재구성(reorg)'과는 다르다는 점에 유의하라. '재구성'은 항상 노드에 이미 있던 데이터보다 최소한 같거나 더 많은 블록을 갖게 되므로, 블록 번호가 거꾸로 가는 것을 본다면 이는 확실히 고장 난 인프라 때문이라고 단정할 수 있다.

불일치 데이터를 측정하는 방식을 이해하기 위해, eth_blockNumber를 총 13번 폴링한 후 다음과 같은 블록 번호 시퀀스를 얻었다고 가정해보자.

eth_blockNumber
Response Sequence

1

1

1

1

1

2

1

1

3

2

1

1

3

이 시퀀스를 보면, 블록 인덱스 6, 7, 9, 10, 11에서 총 5건의 오류를 발견할 수 있다. 이는 블록 6, 7, 9, 10, 11에서 반환된 블록이 예상되는 증가 순서를 따르지 않았음을 의미하며, 이는 내재된 데이터 정확성 문제를 보여준다.

참고: 노드 제공업체가 블록 번호 2에 있다고 기록한 이후, 이어지는 1 값은 모두 잘못된 것으로 간주하며 이는 제공업체가 시간을 거슬러 올라가 1블록 늦은 현재 블록 값을 제공한 것과 동일하다고 본다. 마찬가지로, 노드 제공업체가 블록 번호 3에 있다고 기록한 이후 블록 1이나 2가 나타나는 경우도 이제 어긋난 것으로 간주한다. 이 벤치마킹 테스트를 단순화하기 위해, 개별 제공업체 자체의 데이터 정확성만 명시적으로 측정하며 서로 다른 제공업체 간의 블록 데이터는 교차 비교하지 않는다.

Alchemy 뉴스레터

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

뉴스레터 구독하기

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

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

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