본문 바로가기
개발

블록체인 네트워크를 구성하고 장애/복구 테스트 해보기 (Geth)

by 최승환 2024. 3. 6.

해당 포스트는 회사에서 NFT 프로젝트용, 블록체인 네트워크 구성 업무를 수행 했던 경험을 기록하기 위해, 내 개인 Notion 에 작성했던 글이다. 해당 포스트로 혹시나 도움을 받는 분이 있을까 싶어 공유해 본다.


내가 블록체인을 처음 접했을 때, 개발자로서 굉장히 의문이 들었던 말 중 하나는, ‘블록체인은 서버가 없다’는 것이었다.

 

이 말을 듣자마자 나는 개발자로서, IT 종사자로서, 이해를 할 수가 없었다. 서버가 없으면 연산 처리는 어디서 한다는 건가? 또, 애초에 연산 처리를 담당 하는 물리적인 장치가 없다면 전자적인 컴퓨팅 처리는 어떻게 된다는거지? 하는 생각이 들었다.

 

위 고민에 대해 웹상에서 정보를 찾다 보면, 블록체인은 네트워크에 참여하고 있는 여러 노드에 의해 데이터가 처리된다는 것을 알 수 있다.

블록체인 기술이란 무엇인가요? - 블록체이닝 설명 - AWS

 

블록체인 기술이란 무엇인가요? - 블록체이닝 설명 - AWS

AWS Blockchain 서비스는 사용자의 요구 사항을 지원하기 위해 특별히 제작된 도구를 제공합니다. 이를 사용하여 변경 불가능한 거래 기록을 유지하는 중앙 집중식 원장 데이터베이스부터 중개자를

aws.amazon.com

 

그럼, 최초의 의문으로 돌아와서, ‘서버가 없다’는 말은, 블록체인 네트워크 상에 어떤 물리적인 전자 처리 장치가 (예를 들어 컴퓨팅 서버) 없다는 얘기는 당연히 아닐 것이다. 😅

 

블록체인에서 ‘서버가 없다’ 라는 뜻은 중앙집중식 서버가 없다는 뜻이다. 블록체인 네트워크는 우리가 일반적으로 접하게 되는 웹 서비스와는 네트워크 구성이 다르다.

 

그럼, 우리가 익히 알고 있는 중앙집중식 서버 아키텍처와 블록체인 네트워크 구조인 분산형 아키텍처 구분 해 알아 볼 수 있을 것 같다.

 

중앙집중식 서버 아키텍처란 일반적인 웹 서비스에서 그렇듯이, 중앙 서버 (회사, 조직, 정부 기관 등) 에서 데이터의 관리와 처리를 담당하는 것을 뜻한다. 그리고 클라이언트는 이 중앙 서버와 네트워킹을 통하여 데이터를 주고 받는다.

 

분산형 블록체인 아키텍처 는 네트워크상의 여러 참여 노드들에 의해 데이터의 관리와 처리가 이루어 진다. 여기서 노드란 실제적인 물리적 장치(컴퓨팅 서버) 이며, 각 참여한 노드들은 전체 블록체인의 사본을 가지고 있는다. 각 노드가 전체 블록체인의 전체 사본을 보유한다는 개념은 블록체인 기술의 핵심적인 부분 중 하나이다.

전체 사본은 블록체인에 기록된 모든 거래 내역이다. 새로운 블록(거래 내역 덩어리)이 네트워크에 추가될 때, 모든 노드는 이 변경 사항을 자신의 사본에 업데이트 하며, 모든 노드가 데이터의 일관성을 유지하기 위해 지속적으로 정보 교환을 통해 자신의 사본이 네트워크 전체와 동기화 되어 있는 지 확인한다.

따라서 블록체인 네트워크는 하나의 노드에 문제가 생기더라도 그 외 다른 전체 노드들에서 최신의 정보를 가지고 있으므로 데이터의 무결성과 안전성이 보장된다.

 

위에서 노드가 블록체인의 전체 사본을 보유한다 하였는데, 노드는 일반적으로 두 가지 종류가 있다.

전체 노드(Full Node) 는 위에 언급했던 것과 같이, 블록체인의 전체 데이터를 보유 하고 있다. 이 노드는 모든 거래를 검증하며 네트워크 보안과 무결성을 유지하는 역할을 한다.

경량 노드(Light Node) 는 필요한 최소한의 정보만 저장하여 블록체인 네트워크에 참여한 노드이다. 일반적으로 개인 채굴자들이 이 경량 노드를 사용한다.
현재 시점으로 이더리움 네트워크의 전체 데이터는 약 985GB 이다. 경량 노드는 스토리지 용량보다는 채굴 효율성을 위한 컴퓨팅 파워(GPU) 가 더 중요하다.

 

 

블록체인에 대한 이론 지식은, 이전에 암호화폐 거래소에서 근무하면서도 모호하게 개념만 알고 있지, 실제로는 헷갈렸던 부분들이 많다.

하지만 이번에 블록체인 네트워크를 직접 구성해 보면서 모호하게 알고 있던 지식들을 구체화 할 수 있었던 것 같다.

 

이번에 사내에서 NFT 관련 프로젝트 정부 사업을 진행하면서 프라이빗 네트워크를 구성 할 필요가 있었다.

해당 업무는 내가 충분히 수행할 수 있을 듯 하여 담당하기로 하였다. (원래 사내 개발 인원이 없기도 했지만… 😂)

 

Geth (go-ethreum)

 

Geth 는 이더리움 네트워크를 구성할 수 있는 오픈 소스 중 하나로, 이더리움 블록체인 노드를 구성할 수 있는 도구이다.

Home | go-ethereum

 

Home | go-ethereum

Go-ethereum website, home for the official Golang execution layer implementation of the Ethereum protocol

geth.ethereum.org

 

Geth 는 CLI 환경이 제공되며, Geth 로 해당 컴퓨팅 환경에서 노드를 실행 시키고, 마이닝, 트랜잭션 처리 등 전체 노드, 경량 노드 를 설정할 수 있다.

Light client | go-ethereum

 

Light client | go-ethereum

Introduction to Geth's light sync mode

geth.ethereum.org

 

AWS EC2

이번 NFT 정부 프로젝트는 몇가지 시험을 봐야만 했다.

그 중 조건 중 하나가, 블록체인 네트워크의 노드 장애 대응 테스트였다.

3개 이상의 노드를 구축한 후, 특정 노드에서 장애가 발생 하여 해당 노드가 중단 되었을 때, 다시 재가동 한 후, 체인 네트워크에 Sync 했을 때, 이상 없이 동작해야 한다는 조건이였다.

 

 

 

따라서 EC2 에서 서버 인스턴스를 3개 생성하였다.

각 3개의 노드는, Block 생성 권한이 있는 것과 없는 것으로 나누어 생성한 후, 서로 Sync 시켜 노드 간의 데이터 동기화가 잘 이루어 졌는지를 테스트 할 예정이다.

 

또한 운영 도중, 3개의 노드 중 하나의 노드를 중단(장애) 한 후, 다른 정상 노드에서 마이닝과 Transaction 을 발생 시킨 후, 다시 중단된 노드를 Sync 시켜, 해당 노드에서 동기화가 잘 이루어졌는지 테스트 할 예정이다. (무결성, 안정성 테스트)

 

또한 네트워크 보안 규칙에서 Geth의 JSON-RPC 통신을 위한 포트와, MetaMask의 P2P 통신을 위한 포트도 잊지 않고 열어줘야 한다.

 

Geth 노드 설치

EC2 인스턴스에서 Geth 를 받기 위해 wget 을 사용했다.

wget https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.25-e7872729.tar.gz

tar -xzf geth-linux-amd64-1.9.25-e7872729.tar.gz

 

Genesis Block 생성

Genesis Block 이란, 그 이름처럼 블록체인의 첫 번째 블록을 말한다. 이 Genesis Block 이 블록체인 네트워크의 시작점이 되며, 다른 블록들이 이 Genesis Block 에 연결되어 체인을 형성 하게 된다.

 

Genesis Block 에는 네트워크와 관련된 설정들이 정의 되어 있다. 아래는 테스트넷 구성 시에 필요한, 아주 간소화한 내용들만 정의해 둔 genesis.json 이다.

설정에 clique 라는 내용이 있는데, 이는 블록체인 합의 알고리즘으로 POA (Proof of Authority) 를 사용할 때 정의한다.

 

POA 는 권한을 가진 노드만이 블록체인 상에서 블록의 생성 권한을 갖게 되는 방식이다. 이를 프라이빗 블록체인이라 하며, 리플을 그 예로 할 수 있겠다.

그 반대로, POW (Proof of Work) 합의 알고리즘이 있다. 이는 대표적으로 비트코인과 같은 블록체인에서 사용되며, 모든 노드가 채굴에 참여할 수 있지만, 난이도에 (컴퓨팅 파워) 따라 채굴자가 보상을 얻게 되는 방식이다.

POA 에 비해, POW 는 더욱 탈중앙화 된 방식인데, 블록체인 네트워크의 특징인 분산화를 제공하는 데 핵심 요소라 할 수 있겠다.

// genesis.jon
{
  "config": {
    "clique": {
      "period": 10,
      "epoch": 30000
    }
  },
  "difficulty": "1",
  "gasLimit": "8000000",
  "extradata": "0x00000000000000000000000000000000000000000000000000000000000000002046baa7a5eb69ffb076d6c2b9f922fd196887910000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "alloc": {
    "2046baa7a5eb69ffb076d6c2b9f922fd19688791": { "balance": "300000000000000000000000000000" },
    "E2a5711364e2F6C074dd0ff6F2B67e7eCEC8F41d": { "balance": "400000000000000000000000000000" }
  }
}

 

geth init --datadir data genesis.json

위와 같은 명령으로 네트워크를 초기화 할 수 있다.

참고로 3개의 노드에서 전부 동일한 genesis.json 으로 초기화를 해줘야 한다.

 

노드 초기화가 성공한 후, 아래 커맨드로 각종 필요한 argument 와 함께 geth 블록체인 노드를 실행할 수 있다.

nohup 을 이용하면 geth 를 백그라운드로 실행할 수 있다.

# foreground 실행
geth --datadir data --networkid 12345 --nodiscover --rpc --rpcaddr "0.0.0.0" --rpcport 8545 --rpccorsdomain "*" --rpcapi "admin,eth,miner,web3,net,personal,txpool,clique" --allow-insecure-unlock --verbosity 4 --maxpeers 50 --port 40404 --miner.etherbase "0xa33848ec91f3e0772359e76c60fe83cdaf5357e5" --unlock "0xa33848ec91f3e0772359e76c60fe83cdaf5357e5" --password ./pw console

# background 실행
nohup geth --datadir data --networkid 12345 --nodiscover --rpc --rpcaddr "0.0.0.0" --rpcport 8545 --rpccorsdomain "*" --rpcapi "admin,eth,miner,web3,net,personal,txpool,clique" --allow-insecure-unlock --verbosity 4 --maxpeers 50 --port 40404 --miner.etherbase "0x2046baa7a5eb69ffb076d6c2b9f922fd19688791" --unlock "0x2046baa7a5eb69ffb076d6c2b9f922fd19688791" --password ./pw --cache 1024 &

 

 

 

현재 백그라운드로 실행중인 geth 프로세스에 geth attach 명령어를 이용하여 접속 하였다.

 

geth cli에서, admin.addPeer() 기능을 이용하면, 블록체인 노드 간에 연결이 가능하다.

admin.addPeer("enode://94f72b279bd1c0950353502991690870d13bb7ebbf7cae49911da6761e859669df178712f6ba638232ec5937a9947f1f72f919ecde8a768d98847f583db7df4c@xx.xxx.xxx.xxx:40404?discport=0")

위와 같이 사용할 수 있다. 블록체인의 노드는 enode 라는 주소를 갖고 있다. 해당 주소와, 노드의 원격 IP 주소를 입력해 주면 된다.

 

그 후, admin.peers() 명령으로 현재 연결된 노드들을 확인할 수 있다.

 

서로 연결 된 노드 목록이 배열 형태로 출력된다.

 

 

현재 네트워크의 특정 노드에서 블록을 채굴 중인 상황으로, eth.blockNumber 명령으로 현재 채굴 진행 중인 블록이 잘 반영되고 sync 되고 있음을 확인할 수 있다.

 

현재 블록체인 네트워크와 노드가 정상 작동 중임을 확인 하였으니,

장애 대응/복원 테스트를 위해 작동 중인 첫번째 노드의 geth 프로세스kill 해보았다.

 

pkill geth 커맨드로 프로세스를 강제 종료 시키고, ps | aux geth 커맨드로 geth 가 확실히 종료 되었는 지 확인 하였다.

 

이제, 다른 정상 동작중인 노드에서 MetaMask 를 이용하여 Transaction 을 발생 시킨 후, 장애를 발생 시켰던 첫번째 노드를 다시 복구한 후, 동기화가 제대로 이뤄지는 지 테스트 할 예정이다.

 


 

MetaMask 에서 위와 같이 Transaction 을 발생 시켰다.

 

 

정상 동작 중인 다른 노드에서 eth.getTransaction() 명령으로 Transaction 이 잘 처리 되었음을 확인할 수 있다.

 

그럼 다시 첫번째 노드를 (실행)복구 한다.

 

 

아까와 같이 nohup geth 커맨드로 첫번째 노드를 실행시켜 주었다.

 

 

다시 복구한 첫번째 노드에서 admin.peers 커맨드로 기존에 연결 되었던 노드들과 동기화가 정상적으로 되었음을 확인할 수 있다.

 

 

 

두번째 노드와 첫번째 노드의 BlockNumber 를 확인 하였을 때에도 동기화가 잘 이뤄지고 있다.

 

 

첫번째 노드가 장애(중단) 중일 때 발생했던 Transaction 역시, 복구가 된 후, 잘 조회가 되고 있음을 확인할 수 있다.


이렇게 프라이빗 블록체인 네트워크를 구성하고, 장애 테스트를 해보는 작업을 해보았다.

이전에 암호화폐 거래소에 재직중일 때에는 이런 식으로 직접 블록체인 네트워크를 구성해 보진 않아서, 실제 개념들을 모호하게만 이해하고 있는 경우도 있었다.

하지만, 이렇게 직접 블록체인 네트워크를 구축해 보고, 또 장애, 복구도 해 보니 어느정도 블록체인 생태계에 대해 더 잘 알게 된 것 같다.

위 작업을 진행하면서 몰랐던 블록체인 관련 개념들을 정말 계속 찾아보고 또 찾아 봤던 것 같다… 🤣

회사 정부 지원 사업 관련해서 시작하게 된 일이긴 했지만, 잘 몰랐던 지식들을 많이 학습할 수 있던 기회가 된 것 같아 좋았던 것 같다.