요 몇달 간 회사일에 치어 글쓰기에 너무 소홀했던 듯 하다. 각성하고, 이제 진도를 뽑아보자~

얼마전, Vitalik Buterin 과 Martin이 한국에 다녀갔다. 국내 블록체인 업체인 코인플러그도 퍼블릭 블록체인 기반의 사업성과가 기대에 못미쳐서인지 기업용 블록체인에 눈을 돌린 듯 하다. 자체 블록체인을 발표하고, Ethereum 과 협업을 하고있는 모습이 국내 블록체인 기술의 업그레이드를 위해 노력하는 모습인것 같아 다행이라고 생각한다.

너무 오랜만의 글이라 갈길이 머니 마지막 글에 이어 일단 web3.js 를 사용하는 방법에 대해 본격적으로 이야기 해보자.

▌web3.js 소개


github.com/ethereum 의 repository 목록에서 보이는 내용이다. web3.js 는 Ethereum Compatible JavaScript API 이다. 
일단 아래 그림을 보자.

예전에 외부에서 이더리움을 소개할 때 Ethereum 의 응용 구조에 대해 썼던 자료이다.현재 go Ethereum 의 경우, JSON RPC, IPC 외에도 그림에는 안나와있지만 WebSocket 을 지원한다.

위 구조를 보면 알겠지만, 이전 글까지는 Ethereum 의 JSON RPC 를 통해 어플리케이션이 Ethereum 을 사용하는 방법에 대해 소개 한 것이다.
그런데 JSON RPC 를 사용해서도 충분히 Ethereum 을 사용할 수 있겠지만, 응용 만드는 입장에서는 좀더 편하게 JSON RPC 를 호출해주는 라이브러리가 필요함을 느낀다. 특히 기본적인 Transaction 기반의 응용이 아니라 Smart Contract 를 사용하게 되면, Event 를 처리하거나 Smart Contract 에서 Return 되는 타입을 처리하여야 하는데, 이때 이러한 타입처리 또한 web3.js 라이브러리를 사용하면 편리하다.

web3.js 는 JavaScript 기반으로 Dapp 이나 서비스를 구현할 때 매우 유용하며, 현재는 EthereumJ 도 web3.js 를 지원하는 작업을 하고있다. 실질적으로 JSON RPC API 와 함께 Ethereum 의 표준 API 로 보면 되겠다. web3.js 는 내부적으로 HTTP 나 IPC 를 통해 JSON RPC API 를 호출하도록 되어있다.

▌JavaScript 코드에 web3.js 사용하기

web3.js 는 github/ethereum/web3.js 의 dist 내에 있는 web3.js 를 받아도 되지만,
Browser 에서 사용하려면 bower 를 사용하거나
Node.JS 를 사용한다면 npm 을 사용하면 된다.

이번에는 간단히 bower 로 install 한다.
[goodjoon eth_basic]$  bower install --save web3
crypto-js 와 bignumber.js 에 Dependency 가 걸려있으므로 두개를 추가로 받는다.
(npm 도 마찬가지로 web3 모듈을 설치하면 된다.)

이제 실제로 이전에 JSON RPC API 로 Transaction 보내기 했던 것을 web3.js 로 보내보도록 하고, 보너스로 블록 생성되는 이벤트를 받아보기 위한 Filter 를 하나 설치해보도록 하겠다.
화면은 간단히 아래와 같이 만들어 봤다.


일단 HTML 에서 web3.js 를 import 한다.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../bower_components/web3/dist/web3.js"></script>
    <title>Simple Wallet</title>

그다음, web3.js 를 사용하여 Ethereum Node 에 접속하려면, 아래와 같이 Provider를 지정 해주어야 한다.
var Web3 = require('web3');
var web3 = new Web3();
web3.setProvider(new Web3.providers.HttpProvider('http://localhost:8551'));

위 예제에서는 HttpProvider 를 지정해주었으나, IpcProvider 도 존재한다. Ethereum Node 와 같은 Machine 에서 동작한다면 IPC 로 Interface 하는것이 성능 측면에서 매우 유리하다.


▌Account 의 Balance 가져오기

Account 의 Balance 를 가져오기 위해서는 web3.eth.accounts 프로퍼티를 조사하면 된다. 
function updateBalance() {
    var address = web3.eth.accounts[0];
    var balance = web3.fromWei(web3.eth.getBalance(address), 'ether');

    $('#address').val(address);
    $('#balanceAmount').val(balance);
}

web3.eth.accounts[0]
web3.js API 들은 web3 라는 이름의 객체에 var web3 = new Web3(); 를 통해 할당하였다.
web3.eth 객체 내의 accounts 는 현재 Ethereum Node 에 생성된 계정들의 목록을 배열로 저장하고있다. 현재 내 Node 에 2개의 계정이 있으며, 이중 0 번 계정의 주소를 address 변수에 저장하였다.

web3.eth.getBalance(address)
특정 주소의 Balance 를 가져오는 함수이다. getBalance() 의 리턴값은 Wei 단위의 Balance 이다. address 의 Balance 를 가져와서 web3.fromWei() 함수를 통해 Wei 단위를 Ether 단위로 변경해서 balance 변수에 저장한다. 'ether' 를 지정하지 않아도 fromWei(), toWei() 함수의 기본 변환 단위는 'ether' 이다.

값을 가져와서 화면의 #address 와 #balanceAmount INPUT 필드의 value 로 표현한다.


▌Synchronous vs Asynchronous API

아마 위 함수들이 호출될 때 마다 브라우져나 Node.JS의 Console 에는 Synchronous XHR 은 deprecate 되었다고 경고가 출력될 것이다. 
web3.js 에는 Synchronous 함수와 Property 들이 있으며, 이에 상응하는 Asynchronous 함수들이 있다. 원칙적으로는 Asynchronous API 를 호출해야 한다. accounts 프로퍼티 대신 web3.eth.getAccounts(address, callback) 을 주도록 되어있으며, web3.eth.getAccounts(address, function(err, addresses) { console.log(addresses)}); 처럼 Callback 을 통해 결과를 받아야 한다.
(RPC API 는 deprecate 된 Synchronous 호출을 아직 실행 해주지만, IPC 방식은 아예 호출이 불가능하다)

▌Transaction 보내기

Ether 의 이체, Smart Contract 의 Deploy (Creation), Smart Contract 의 함수 실행 (Message) 모두 하나의 Transaction 발생 함수를 통해 실행한다. 바로 web3.eth.sendTransaction() 함수이다.
sendTransaction() 함수는 앞으로 지속적으로 사용할 것이며 사용법은 매우 간단하다.

web3.personal.unlockAccount(web3.eth.accounts[0],'1111');

일단, Page 가 로드되는 시점 즈음에서 account 를 unlock 해두도록 한다. 이전 RPC API 편에서도 이야기 했듯이, Account 를 사용하기 전에는 Account 를 Unlock 해주어야 한다. 만약 Ethereum 실행 시에 --unlock 옵션을 주고 --password <패스워드파일> 을 주어서 Node 의 BootUp 시에 Unlock 을 이미 하였다면 unlockAccount() 를 실행 할 필요는 없다.

Send 버튼을 눌렀을 때에 실행되는 코드는 아래와 같다.
var toAddress = $('#toAddress').val();
var sendAmount = web3.toWei($('#sendAmount').val(), 'ether');

var txHash = web3.eth.sendTransaction({
    from: web3.eth.accounts[0],
    to: toAddress,
    value: sendAmount
});

console.log(txHash);

web3.eth.sendTransaction(object) 함수에서 object 는 보낼 Transaction 의 내용이 정의 된 Object 이다.
     - from : Transaction 을 보내는 from 주소
     - to : Transaction 의 Destination 주소. 만약 Smart Contract Creation Transaction 인 경우, to 를 지정하지 않는다.
     - value : 보낼 Balance 의 양 (Wei 단위)
     - gas : 이번에는 Gas 양을 지정하지는 않았지만, Ethereum 은 기본적으로 90,000 Gas 를 적어 보내게 되어있다. data 필드를 사용하지 않는 기본 이체 Transaction 의 소모 Gas 는 현재 21,000 Gas 이다.

이 sendTransaction() 함수의 리턴값은 Transaction 의 Hash 값이다. Transaction 의 Hash 값은 Transaction 의 형식 자체에 오류만 없다면 Node 에서 즉시 리턴이 오는 값이다. Miner 나 타 Node 의 Validation 작업과는 무관하다. 

Transaction 이 Block 에 잘 묶여졌는지 확인하기 위해서는 
web3.eth.getTransactionReceipt(txHash) 로 Receipt 를 확인해야 한다. 만약 null 이 리턴되었다면 Transaction 은 Block 에 묶이지 않는 것이다.


▌Block Filter 

Ethereum 에서 새로운 블록이 나오거나 Smart Contract 의 Method 내에서 Event 를 실행(Trigger) 시켰을 때, 특정 Address 나 Topic 에 해당하는 Log 를 알림 받으려고 할 때 사용할 수 있는 기능이 바로 Filter 객체이다. 그중 기본적으로 최신 블록이 생성되어 Mined/Import 되었을 때 이벤트를 받을 수 있도록 하여 좀더 동적인 느낌이 나도록 해보겠다.

var blockFilter = web3.eth.filter('latest');
blockFilter.watch(function(error, blockHash) {
    var block = web3.eth.getBlock(blockHash);
    appendLog('New Block('+block.number+')['+block.hash+'] / ' + block.transactions.length + ' TXs');
});

위 처럼 web3.eth.filter() 함수를 통해 Block 에 대한 Filter 를 걸 수 있다. 'latest' 를 넣어주면 최신 생성된 블록이 있는 경우 Filter 로 잡히게 되며, 'pending' 을 적어주면 Pending 중인 블록 (마이닝 대상)을 보여준다. 또한 Smart Contract 의 Transaction Receipt 내의 Log 에 한하여 Address 나 Topic 을 옵션으로 하여 Filter 할 수도 있는데, 이건 다음번 Smart Contract 하면서 이야기 해보도록 하겠다.

이렇게 코드를 만들고 나면 최종 아래와 같은 화면을 볼 수 있다.


▌결과화면


이처럼 web3.js 를 사용하는 방법은 매우 간단하고 쉽다. 만약 Transaction 에 Custom 한 데이터를 포함하고 싶다면 sendTransaction() 시에 { data : '<HEX값>'} 을 추가하여 보내기만 하면 된다. Bitcoin 이 OP_RETUN 코드 실행으로 가져올 수 있는 40 Byte 의 임의의 데이터 공간만을 제공하는것에 비해 Gas 만 충분하다면 (1 Byte 당 5 Gas) 큰 데이터를 넣는것도 문제 없다. 실제로 수십KB 이상의 이미지 Binary 를 Homestead 와 같은조건으로 놓고 테스트해 본 결과 잘 들어간다. 

다음은 Smart Contract 에 대한 개념과 개발 방법을 시작으로, Smart Contract 에 대하여 본격적으로 연재 해보도록 하겠다.



반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,