스마트 컨트랙트(Smart Contarct) 개발환경 구축 (Geth)



블록체인은 중앙 집중화된 서버의 형식으로 동작하지 않고 각각의 노드들이 분산 되어 서로간의 연결(Peer to peer)로 이루져 있다. 이렇게 서로 노드간의 통신을 할 수 있는 표준을 준수하는 프로그램들을 “이더리움 클라이언트 프로그램”이라고 정의한다. 이더리움 클라이언트는 다양한 언어로 개발할 수 있으며 그중 많이 사용하는 것이 구글에서 개발하는 “GO” 언어로 개발된 “Go Ethereum”이다.

실제 이더리움 클라이언트 프로그램은 이더리움의 메인 네트워크에 접속하고 하나의 노드로 동작하도록 구성되어 있다. 만약 이러한 클라이언트를 이용하여 스마트 컨트랙트를 작성하고 배포한다면 우리는 채굴자에게 실제 비용(가스비라고 한다)을 이더로 지불해야 한다.

프로그램을 개발해 본 독자라면 누구나 동의하겠지만 프로그램이 한번에 완벽하게 끝나는 경우는 없을 것이다. 항상 개발하고 테스트 하고 오류를 수정하는 과정을 거쳐야 하는데, 이 때마다 비용을 지불하면서 개발을 하기에는 너무 큰 어려움이 있다. 이러한 점을 해결해 주기 위하여 이더리움 클라이언트는 메인 네트워크에 접속하지 않고 개인 네트워크를 직접 설정하여 구성할 수 있는 방법을 제공해 준다.

일반적으로 스마트 컨트랙트를 개발하고 배포하는 과정은 “Test RPC(사설 네트워크)”에서 개발 및 디버깅을 한 후 이더리움 메인 네트워크와 동일한 구조를 가진 “TestNet”에서 테스트를 하고 완료되면 메인 네트워크(Ethereum Main Network)에 배포한다.

1. Go Ethereum


이더리움 네트워크의 구조를 알아보기 위해서는 사용에는 조금 불편하지만 “Go Ethereum(이하 Geth)를 이용하는 방법에 대해 알아보는 것이 필요하다. “Geth”는 “HTTP JSON RPC”, “web3.js” 및 “Solidity” 인터페이스를 제공해 주며, 이를 이용하여 스마트 컨트랙트를 작성하거나 계정간의 데이터를 전송할 수 있다. 실제 책에서 본 과정을 진행하면서 우리는 가나슈(Ganache)라는 테스트 네트워크를 이용할 것이지만 기본적인 개념을 위하여 먼저 “Geth”를 설치해 보도록 하자.

먼저 “Geth”의 공식 사이트인 https://geth.ethereum.org/downloads/ 에 접속하여 독자의 운영체제에 맞는 프로그램을 다운로드 받는다.

[그림 1] Go Ethereum 다운로드 페이지 (https://geth.ethereum.org/downloads)


2020년 6월 현재 “Geth”는 v1.9.15까지 배포되었다. 본 책에서는 윈도우즈를 기반으로 설명할 예정이므로 “Geth 1.9.15 for Windows”를 클릭하여 다운로드 받은 후 설치 파일을 실행한다. 설치 파일을 실행하면 다음과 같이 라이센스 부분에 대한 동의를 요구하는 대화상자가 나타난다.

[그림 2] 라이센스 동의


[I Agree]를 클릭하여 다음으로 이동하면 설치할 항목을 지정할 수 있는 대화상자가 나타난다.

[그림 3] 설치 파일의 선택


노드를 형성하고 블록 체인에 접속하기 위한 “Geth” 이더리움 클라이언트와 콘솔 모드에서 개발을 도와줄 수 있는 “Development tools”를 선택한 후 [Next] 버튼을 누른다.

[그림 4] 설치 경로의 지정


“Geth”가 설치될 디렉터리를 지정한 후 [Install]을 클릭하면 설치가 진행된다.

[그림 5] 설치의 진행


설치 과정중에 [그림 6]과 같이 환경 변수 설정에 대한 정보가 나타난다.

[그림 6] PATH 설정


“Geth”는 설치되면서 윈도우 환경변수에 실행 파일에 대한 경로를 지정하도록 되어 있는데, 정상적으로 경로가 업데이트 되는 경우에도 가끔 “PATH not updated, …“이라는 메시지가 나타난다. 설치가 완료된 후 정상적으로 “Geth” 가 실행되지 않는 경우에는 시스템 환경변수를 설정해 주어야 한다. 설치가 완료되면 [Close] 버튼이 활성화 된다. [Close] 버튼을 눌러 프로그램의 설치를 마친다.

정상적으로 설치되었는지 확인하기 위하여 명령 프롬프트를 관리자 모드로 실행한 후 프롬프트 상에 다음과 같이 “Geth” 실행 명령을 입력한 후 엔터키를 입력하여 구동시킨다.

c:\Users\MarkLee\geth


정상적으로 “Geth”가 실행되면 [그림 7]과 같이 환경 설정 정보들이 나타나면서 구동을 시작한다.

[그림 7] “Geth”의 실행


앞에서 “Go Ethereum”은 이더리움 클라이언트로 메인 네트워크에 접속하여 노드를 형성한다고 하였다. “Geth”를 기동하면 실제 이더리움 네트워크에 접속하여 블록들을 다운로드 받기 시작한다. 실제 모든 블록의 정보를 다운로드 받으려면 네트워크 상황에 따라 다르지만 하루 정도의 시간이 소요되고 저장되는 데이터도 상당하다.

우리는 이더리움 메인 네트워크의 노드로 ‘Geth”를 사용하는 것이 아니라 사설(private) 이더리움 네트워크를 설치하고 스마트 컨트랙트를 개발하는 것이 목적이므로 프로그램을 종료 시킨 후 (Ctrl + C 키 이용) 사설 네트워크를 구동하도록 하겠다.



시스템 환경 변수 설정
윈도우 시스템은 실행 파일의 경로를 PATH에 기록하여 어떠한 디렉터리에서도 실행이 가능하도록 설정해 놓을 수 있다. [제어판] → [시스템 보안] → [시스템]으로 이동한 후 왼쪽의 [고급 시스템 설정]을 클릭한다.

[그림 8] 고급 시스템 설정


시스템 속성 설정창에서 [환경 변수] 부분을 클릭 한다.

[그림 9] 시스템 Path 선택


하단의 “시스템 변수(S)” 부분에서 “Path” 부분을 선택한 후 [편집] 버튼을 클릭한다. [그림 10] 환경 변수 추가


환경 변수 부분에 설치한 “Geth” 의 경로가 나타나지 않는다면 [새로 만들기(N)]를 클릭하여 설치된 경로를 추가하여 주면 된다.




1.1 사설 이더리움의 설치


공용 이더리움에 DApp을 배포하게 되는 경우 비용(Gas)이 발생하게 되므로 사설 이더리움을 설치하여 개발한 후 최종본을 공용 이더리움에 배포를 하는 것이 일반적이다. 사설 이더리움 네트워크를 설치하기 위해서는 다음과 같은 환경을 설정하여야 한다.

1) 제네시스 블록(Genesis Block) 생성: 이더리움 네트워크에서 사용되는 블록체인의 최초 시작 블록으로 이전 블록을 지시하는 정보를 포함하고 있지 않으며 어떤 계정에서 얼만큼의 암호화폐를 가지고 있는지 지정해 준다.

2) Data Directory 설정: 이더리움이 동작하면서 발생하는 데이터(계좌 정보, 블록 정보 등)들이 저장될 기본 디렉터리를 지정한다. 이더리움이 동작하면서 하위에 여러 디렉터리가 생긴다.

3) Network ID 설정: 이더리움 네트워크 ID 정의. 10 이하의 네트워크 아이디는 기존의 네트워크에 할당되어 있다. “1”의 경우 메인 네트워크를 의미하며 “3”의 경우에는 “Ropsten” 테스트 네트워크 등으로 사용된다. 사설 네트워크를 구성하고 외부와 통신하지 않는 경우에는 크게 상관할 필요 없지만, 10이상의 값을 상용하는 것이 좋다.

4) Node Discovery 비활성화: 이더리움은 다른 노드들과 상호작용을 하게 구성되어 있다. 이런 경우 다른 노드의 정보와 동기화 등에 시간이 발생하게 되므로 이더리움이 다른 노드를 찾아 peer로 등록하는 과정을 비활성화한다.

위의 4가지를 지정함으로 사설 네트워크를 구성할 수 있는데, 기동시 부여할 수 있는 옵션은 다음과 같다.



1.1.1 Geth 클라이언트 계좌 생성 및 조회


사설 네트워크의 구축에 앞서 Geth 클라이언트용 계좌(Account)를 개설한다. 처음 생성하는 계좌는 “Base Address” 또는 “Coin base”라고 부르며 추후 채굴(mining)을 하면 모든 이더(Ether)가 쌓이는 기본 계정이다.

geth --datadir "c:\geth\data" account new


[그림 11] 계정의 생성 및 Key File의 확인



“–datadir” 옵션을 지정하여 생성되는 계좌의 정보가 저장될 위치(실제 계좌의 정보는 해당 디렉터리 밑에 “keystore”에 저장된다) 를 지정하고 신규 계정을 생성하는 명령어를 실행하면 해당 계좌에 대한 비밀 번호를 입력하라고 요청 받는다. 비밀번호와 확인을 위해 두번의 동일한 비밀번호를 입력하면 “Geth”에서 사용할 수 있는 계좌가 “0x 05f32de3f4abb1ca3a2de5fa8842d39fc462ecb1”와 같이 생성된다(이 주소는 각자 다르게 생성된다).

위에서 지정한 “–datadir” 밑의 “keystore” 디렉터리로 이동하면 실제 하나의 데이터 파일이 생성된 것을 확인할 수 있다. 파일의 내용은 생성된 주소와 암호화된 개인키 정보 등을 포함하고 있는 JSON 형태로 되어있다. 이 파일은 실제 비밀번호만 알고 있으면 복호화 할 수 있으며, 복호화된 개인키로 계정을 이용할 수 있기 때문에 잘 보관하여야 한다.

생성된 계좌의 목록은 “account list”를 통해 확인할 수 있다.

geth --datadir "c:\geth\data" account list


[그림 12] 생성된 계좌의 목록 확인



1.1.2 사설 네트워크(Private Network)의 제네시스 블록 정의


제네시스 블록은 이더리움 블록의 가장 첫번째 블록으로 이전 블록에 대한 정보를 가지고 있지 않는 유일한 블록이다. 제네시스 블록은 사설 네트워크의 특성을 정의하는 최초의 블록이며 사설 네트워크를 구성하는 경우 정의가 필요하다. 제네시스 블록은 json 형태로 구성된다. 다음은 제네시스 블록의 예이다.

{
    "config": {
        "chainId": 15, 
        "homesteadBlock": 0,
        "eip155Block": 0,
        "eip158Block": 0
    },
    "difficulty" : "1024",
    "gasLimit" : "2100000",
    "alloc": {
        "05f32de3f4abb1ca3a2de5fa8842d39fc462ecb1": {"balance": "300000000"}
    }
}



Genesis 블록을 생성하기 위하여 앞에서 생성한 json형태의 스크립트를 메모장등을 이용하여 작성한 후 저장하고 “init” 인자를 이용하여 geth를 실행한다(예제에서는 c:/geth/script 디렉터리 밑에 genesis.json 파일명으로 저장하였다).

geth --datadir "c:\geth\data" init "c:/geth/script/genesis.json"


[그림 13] 제네시스 블록의 생성



정상적으로 Genesis 블록이 생성되었으면 “Successfully wrote genesis state” 문구가 화면에 나타난다.

1.1.3 사설 이더리움 네트워크 실행


“Geth” 이더리움 클라이언트는 두가지 모드로 실행이 가능하다.

1) 단순 이더리움 클라이언트 실행:
추가적인 설정의 변경없이 기동하는 경우.

2) 이더리움 클라이언트 실행과 동시에 자바스크립트 콘솔 환경으로 접근:
API를 이용하여 옵션을 조정하거나 채굴, 계좌의 생성 등을 수행할 수 있다. 콘솔 환경을 구동하고자 하는 경우에는 옵션 부분에 “console”을 추가한다. 이제 제네시스 블록까지 생성을 마쳤으므로 사설 이더리움을 동작하기 1.1에서 알아본 옵션을 이용하여 다음과 같이 실행한다.

geth --identity “MyNetwork” --networkid 15 --datadir "c:/geth/data" --port "30303" --rpc --rpcaddr 0.0.0.0 --rpcport "8545" --rpcapi "eth, net, web3, miner" --rpccorsdomain "*" --nodiscover --nat "any" console


[그림 14] 외부 접속을 지원하는 환경의 Geth


정상적으로 수행되면 명령 프롬프트로 돌아오지 않고 Console을 이용하여 이더리움이 제공하는 기능들을 활용할 수 있도록 “>” 프롬프트가 나타난다(나오지 않는 경우에는 엔터키를 치면 나타날 것이다).

1.1.4 Geth 콘솔의 활용


우리는 “Geth”를 실행시키면서 맨 뒤에 “console”을 명시하여 자바스크립트 콘솔 모드에서 명령어 수행이 가능하다고 이야기하였다. 여기서는 몇가지 기능을 테스트해 보도록 하겠다.

1) 계좌 목록(accounts) 및 잔고(balance) 확인
클라이언트 노드에 계설된 계좌는 “account”라고 하며 목록을 확인하기 위하여 “eth.accounts”를 사용한다.

> eth.accounts


[그림 15] 계정 목록의 확인 - eth.accounts


우리는 먼저 “Geth”를 생성하고 하나의 계좌를 생성하였다. 동일한 계좌의 목록이 조회됨을 확인할 수 있다. 조금 눈치가 빠른 독자의 경우에는 “account”라는 메소드를 사용하지 않고 “accounts”라는 복수형 이름을 사용한 것을 알 수 있을 것이다. “Geth”의 계정은 리스트 형태로 관리되며 각각의 인덱스를 이용하여 접근할 수 있기 때문에 “accounts”를 사용하는 것이다.
특정 계좌의 잔고를 확인하기 위하여 “eth.getBalance()”를 사용한다

> eth.getBalance(eth.accounts[0])
> eth.getBalance(eth.coinbase)


[그림 16] 계정 잔고의 확인 - eth.getBalance()


제일 먼저 생성한 계좌는 accounts[0]에 저장되어 있으며, 모든 채굴된 이더가 모인다는 의미로 “coinbase”로 지정되어 있다. 앞서 제네시스 블록을 생성하면서 계좌에 “300000000”을 할당하였는데 정상적으로 입금되어 있는 것을 확인할 수 있다. 이더리움 네트워크의 계좌가 가지고 있는 이더는 “wei”라는 가장 작은 값을 기준으로 계산된다. 1이더는 1018 wei이다. 다음은 이더의 단위를 나타낸다.

명칭 Wei 기준 Ether 기준
WEI 1 0.000000000000000001
Ada 1000 0.000000000000001
Fentoether 1000 0.000000000000001
Kwei 1000 0.000000000000001
Mwei 1000000 0.000000000001
Babbage 1000000 0.000000000001
Pictoether 1000000 0.000000000001
Shannon 1000000000 0.000000001
Gwei 1000000000 0.000000001
Nano 1000000000 0.000000001
Szabo 1000000000000 0.000001
Micro 1000000000000 0.000001
Microether 1000000000000 0.000001
Finney 1000000000000000 0.001
Milli 1000000000000000 0.001
Milliether 1000000000000000 0.001
Ether 1000000000000000000 1


출력값을 이더로 변경하고 싶은 경우에는 “web3.fromWei()”를 사용하여 단위 변환이 가능하다

[그림 17] 계정 잔고의 단위 변환 - web3.fromWei()


2) 채굴(Mining)
이더리움은 거래가 이루어지는 경우 채굴을 통하여 블록에 거래의 내역을 쓰는 과정이 이루어진다. 즉, 스마트 컨트랙트를 작성하고 개인 네트워크에 올려 놓았다 할지라도 채굴이 이루어지지 않으면 그 거래는 블록체인 내에 기록되지 않는다는 것을 의미한다.
채굴 기능을 활성화 하는 방법은 geth를 실행시킬 때 인자로 “–mine” 옵션을 함께 넣어주는 방법과 콘솔에서 실행시키는 방법을 사용할 수 있다. 콘솔 상태에서 채굴을 시작하기 위해서는 프롬프트 상에서 “miner.start()”를 실행시킨다. 이 때 miner는 “–rpcapi” 옵션에서 “miner” API를 추가한 상태여야 한다.

> miner.start()
> miner.stop()


[그림 18] 채굴의 시작과 종료 - miner.start() / miner.stop()



Related Posts