근래에 블록체인에 꽤 관심이 생겼다. 생태계를 쭉 둘러봤는데, 대략적으로 dApp이나 Consensus 엔진 정도가 눈에 먼저 보인 것 같다.

차차 전반적으로 이해한 걸 바탕으로 글을 쓸 예정이다. 다만 우선 첫글은 가장 low-level 레이어인 합의 엔진 (Consensus Engine)을 이론이랑 구현체를 까보며 이해해보려고 한다.

이런 게 왜 필요할까? 그리고 구현은 왜 그렇게 돼있을까? 이걸 알기 위해선 우선 분산 시스템을 이해할 필요가 있다.

분산 시스템

일단 사전적인 정의로는, 여러 독립적인 노드(컴퓨터)들이 네트워크로 연결되어 하나의 공동 목표를 수행하기 위한 시스템이다.

예를 들어..

  • Redis에서 샤딩 기능을 이용해서 여러 노드가 연결되고 캐싱을 수행하면 분산 시스템이다. (장애 복구)
  • 인프라에서 de facto인 쿠버네티스같은 경우도 동일하다.

결국 여러 노드가 동일한 순서의 로그를 통해 동일한 State를 갖게 만드는 것이 핵심이다. 이걸 학술적으로는 **상태 머신 전파(State Machine Replication)**라고 부른다.

Raft 합의 알고리즘

대표적으로 흔히 사용되고 있는 것은 Raft다.

쿠버네티스의 etcd에서 사용하고, RedisSentinel이나 Cluster의 리더 선출 과정에서 Raft-like를 사용한다.

함축적으로 플로우를 설명하자면 다음과 같다:

  1. 리더가 없을 시 리더 투표를 한다.
  2. 투표가 정족수, 즉 과반수가 넘으면 해당 노드를 리더로 승격시킨다.
  3. 리더가 상태 전파를 담당한다.
  4. 위 과정 반복

이건 모든 노드들이 '착하다' 라는 전제이다. 만약 악의적인 노드가 있다고 하고, 해당 노드가 리더가 되면 잘못된 로그를 줘서 시스템을 붕괴시킬 수도 있다.

위의 예시들은 내부 시스템에서 사용하고 있기 때문에 (물론 요새 Zero-Trust로 얼추 방어한다) 이런 경우가 많지 않겠지만, 블록체인은 다르다. 누구나 참여할 수 있기 때문에 악의적인 노드가 있을 확률이 존재한다.

이를 해결하기 위해 고안된 것이 비잔틴 장애 허용(Byzantine Fault Tolerance, BFT) 알고리즘이다.

비잔틴 장애 허용 알고리즘

알고리즘을 알기 전 배경적으로 알아야 할 딜레마적 개념이 있는데, 비잔틴 장군 문제이다.

배경은 이렇다:

비잔틴 제국의 장군들이 적의 도시를 포위하고 있다.

해당 전투에서 이기려면 양자택일을 해야한다: 모든 장군이 전부 공격하거나, 모든 장군이 전부 후퇴하거나

현실적인 제약은 다음과 같다:
- 장군들끼리는 전령을 통해서만 소통 가능하다.
- 장군들 중에서 배신자가 몇몇 섞여있다. 예를 들어, 이런식으로: 몇몇 장군들에게는 후퇴하라고하고 몇몇 장군들에게는 공격하라고 한다.

이 상황에서 어떻게 배신자들을 뚫고 승리할 수 있을까?

위 내용을 해결하기 위한 여러 합의 이론들이 존재한다. 크게 두가지로 나눌 수 있는데

  • PoW: 연산력 기반 합의 (메세지에 이어진 체인이 가장 긴 게 진실로 합의됨)
  • BFT: 메세지들 던지면 2/3 노드들이 검증 후 메세지를 합의함

와 같이 나눌 수 있다.

여기까지가 백서 내용이다. 백서 자체도 장황하지만.. 분산 시스템이 다 그렇듯 엣지케이스 처리를 엄청나게 해줘야 하기 때문에 구현체 내부 동작도 중요하다.

현재 공부중인 내용이라 부족한 부분이 존재할 수 있다. 여러가지 엣지케이스가 생각나는데, 다음 글에서 어떻게 핸들링하는지 알아보도록 하겠다.